ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [공룡책] Ch 4. 스레드와 병행성
    공부/운영체제(OS) 2022. 4. 26. 16:35
    반응형

    이 글은 공룡책을 읽고 정리한 글입니다.


     

     

     

    0. 소개


    3장에서는 한 프로세스가 하나의 제어 스레드로 프로그램을 실행한다고 가정하였는데, 현대에서는 한 프로세스가 다중 스레드를 포함하는 특성을 제공한다. 그리고 다중 CPU를 제공하는 최신 다중 코어 시스템에서 스레드 사용을 통한 병렬 처리의 기회를 식별하는 것이 중요하다.

    그래서 이 장에서는 스레드와 다중 스레드 컴퓨터 시스템에 대해 자세히 살펴보려고 한다.


     

     

     

    1. 개요


    스레드

    - CPU 이용의 기본 단위

    - 스레드 ID, 프로그램 카운터(PC), 레지스터 집합, 스택으로 구성

    - 같은 프로세스에 속한 다른 스레드와 운영체제 자원들을 공유

     

    현대 운영체제는 한 프로세스가 여러 개의 프로세스를 가지고 있어서 프로세스는 동시에 하나 이상의 작업을 수행할 수 있는점이 단일 스레드 프로세스와 다중 스레드 프로세스와의 차이점이다.


    1) 다중 스레드가 만들어진 이유

    만약 웹 서버가 단일 스레드 프로세스로 작동한다면, 서버는 단일 프로세스로 한 번에 하나의 클라이언트만 서비스할 수 있게 되어 클라이언트는 자신의 요구가 서비스되기까지 매우 긴 시간이 기다리게 된다.

    이것에 대한 해결책은 서버가 요청을 받는 일을 하나의 프로세스로 동작을 하게 만드는 것이다. 요청을 받을 때마다 프로세스를 하나 만드는 것은 너무 큰 오버헤드를 가지고, 요청은 여러 클라이언트에게 받을 수 있으니 해당 프로세스에 여러 개의 스레드를 할당하여 요청을 받는 일만 처리할 수 있도록 한다.

     

    이렇게 한 프로세스에 여러 개의 스레드를 할당하면 일을 더 효율적으로 처리 할 수 있기 때문에 최신 다중 코어 시스템에서는 다중 스레드를 사용하고 있다.

    참고로 프로세스를 만드는 것도 오버헤드를 가지고 있지만, 스레드를 만드는 것도 오버헤드를 가지고 있기 때문에 나중에는 할 일이 없는 스레드를 제거하지 않고, 스레드 풀이라는 곳에 반납하는 기술을 사용하게 된다.


    2) 다중 스레드 프로그래밍의 장점

    - 응답성

    프로그램의 수행이 계속되는 것을 허용한다.

    만약 단일 스레드로 프로그램을 실행한다면 시간이 많이 걸리는 연산을 선택할 경우, 해당 연산이 끝날 때까지 프로그램은 사용자에게 응답을 하지 않을 것이다.

    하지만 다중 스레드로 프로그램을 실행한다면 긴 연산을 별도의 스레드에 맡기고, 다른 스레드가 사용자에게 응답을 받을 수 있게 된다. 그러면 프로그램은 계속 사용자에게 응답할 수 있다.

     

    - 자원 공유

    프로세스는 공유 메모리 / 메시지 전달 기법을 통해야한 자원을 공유할 수 있지만, 스레드는 자동으로 자기가 속한 프로세스의 자원들과 메모리를 공유한다.

    이것은 한 응용 프로그램이 같은 주소 공간 내에 여러 개의 다른 작업을 하는 스레드를 가질 수 있다는 장점을 가지고 있다.

     

    - 경제성

    프로세스 생성을 위해 메모리와 자원을 할당하는 것은 비용이 많이 든다. 하지만 스레드는 프로세스 내의 자원을 공유하기 때문에 프로세스를 생성하는 것보다 스레드를 생성하고 문맥 교환을 하는 것이 더 경제적이다.

     

    - 규모 적응성

    다중 처리기(멀티 프로세스) 구조에서는 각각의 스레드가 다른 처리기에서 병렬로 수행될 수 있기 때문에 다중 스레드의 장점이 극대화된다.


     

     

     

    2. 다중 코어 프로그래밍


    병행 실행
    병렬 실행

     

    다중 코어란 하나의 컴퓨터 칩에 여러 컴퓨팅 코어를 배치하는 것이다. 각 코어는 운영체제에서 별도의 CPU로 보이게 된다. 이때 다중 스레드 프로그래밍은 이러한 여러 컴퓨터이 코어를 효율적으로 사용하고 병행성을 향상시키는 기법을 제공한다.

     

    이때 병행과 병렬의 차이를 알아야 한다.

    병행 시스템 모든 작업이 진행되게 하여 둘 이상의 작업을 지원하는 것이고, 병렬 시스템 둘 이상의 작업을 동시에 수행하는 것이다.

    그래서 단일 스레드 프로세서만 있을 때는 CPU 스케줄러가 프로세스를 아주 빠르게 전환하여 병행 실행을 하는데, 사용자에게 병렬 실행하는 것처럼 보여주었다. 하지만 다중 스레드 프로세스는 정말로 병렬 실행을 가능하게 해주었다.


    1) 다중 코어 시스템을 위해 프로그래밍하는데 필요한 도전 과제

    - 태스크 인식 (identifying tasks)

    응용 프로그램을 분석하여 병렬로 실행될 수 있는 태스크를 찾아서 나누는 작업이 필요하다. 

     

    - 균형 (balance)

    병렬로 실행될 수 있는 태스크를 찾는 것도 중요하지만, 해당 태스크들이 전체 작업에 균등한 기여도를 가지도록 나누는 것도 중요하다.

     

    - 데이터 분리 (data spliting)

    태스크 인식과 비슷하다. 태스크가 접근하고 조작하는 데이터 또한 개별 코어에서 사용할 수 있도록 나누어져야 한다.

     

    - 데이터 종속성 (data dependency)

    태스크가 접근하는 데이터는 둘 이상의 태스크 사이에 종속성이 없는지 확인해야한다. 만약 종속적인 경우 프로그래머가 데이터 종속성을 수용할 수 있도록 잘 동기화해야 한다.

     

    - 시험 및 디버깅 (testing and debugging)

    프로그램이 다중 코어에서 병렬로 실행될 때, 다양한 실행 경로가 있으니 이런 것을 시험하고 디버깅해야한다.


    데이터 병렬 실행, 태스크 병렬 실행

    2) 병렬 실행의 유형

    병렬 실행의 유형은 데이터 병렬 실행과 태스크 병렬 실행이 존재한다.

     

    - 데이터 병렬 실행

    동일한 데이터의 부분집합을 다수의 계산 코어에 분배한 뒤 각 코어에서 동일한 연산을 실행하는데 초점을 둔다.

     

    ex) 단일 코어 시스템에서 크기가 N인 배열을 더하는 경우

    위 사진과 같이 코어가 4개라면 아래와 같이 네 개의 스레드는 각자 계산 코어에서 병렬로 실행된다.

    코어 0 스레드 → 원소 [0]부터 원소 [(N-1)/4 - 1]까지 저장

    코어 1 스레드 → 원소 [(N-1)/4]부터 원소 [2 * (N-1)/4 - 1]까지 저장

    코어 2 스레드 → 원소 [2 * (N-1)/4]부터 원소 [3 * (N-1)/4 - 1]까지 저장

    코어 3 스레드 → 원소 [3 * (N-1)/4]부터 원소 [(N-1) - 1]까지 저장

     

    - 태스크 병렬 실행

    데이터가 아니라 태스크(스레드)를 다수의 코어에 분배하고, 각 스레드는 고유의 연산을 실행한다.

     

    ex) 대학교 성적 처리

    평균을 구하는 태스크, 분산을 구하는 태스크가 있으면 이 두 개의 태스크를 각각의 코어에 분배하는 것이다. 그래서 데이터 자체는 공유하게 되고, 스레드는 각자 다른 태스크를 수행하게 된다. 이 과정에서 스레드는 다른 스레드에서 계산한 것을 반복할 수도 있다. 예를 들어 분산을 구할 때 평균을 구해야하므로 이게 반복이라고 할 수 있다.


     

     

     

    3. 다중 스레드 모델


    사용자 공간에 있는 사용자 스레드, 커널 공간에 있는 커널 스레드

    스레드는 두 가지 종류가 있다. 하나는 사용자를 위한 사용자 스레드, 커널을 위한 커널 스레드이다.

    사용자 스레드커널 위에서 지원되며, 커널의 지원없이 관리된다. 하지만 커널 스레드운영체제에 의해 직접 지원되고 관리된다.

    커널 스레드와 사용자 스레드는 연관 관계를 확립하는데 세 가지 방법이 쓰인다.


    1) 다대일 모델 (many-to-one)

    많은 사용자 스레드를 하나의 커널 스레드로 사상(mapping)한다. 스레드 관리는 사용자 공간의 스레드 라이브러리에서 이루어지기 때문에 효율적이지만, 한 스레드가 봉쇄형 시스템 콜을 하면 전체 프로세스가 봉인된다는 단점이 있다.

    그리고 한 번에 하나의 스레드만이 커널에 접근할 수 있기 때문에 다중 스레드가 다중 코어 시스템에서 병렬로 실행될 수 없다. 그래서 이것은 안쓴다.


    2) 일대일 모델 (one-to-one)

    각 사용자 스레드를 각각 하나의 커널 스레드로 사상한다. 이러면 다대일 모델과 다르게 하나의 스레드가 봉쇄적 시스템 콜을 하더라도 다른 스레드는 문제 없기 때문에 더 많은 병렬성을 제공한다. 거기다가 다중 처리기에서 다중 스레드가 병렬로 수행되는 것을 허용한다.

    하지만 유일한 단점은 사용자 스레드의 수만큼 커널 스레드를 만들어야해서 시스템 성능에 부담을 줄 수 있다.

    Linux, Windows가 일대일 모델로 구현한다.


    3) 다대다 모델 (many-to-many)

    여러 개의 사용자 스레드를 여러 개의 커널 스레드에 멀티플렉스한다.

    다대다 모델은 다대일 모델과 일대일 모델의 단점을 어느정도 해결한 모델이지만 실제로 구현하기가 어렵고, 현대에 들어서 처리 코어의 수가 증가함에 따라 커널 스레드를 많이 만들어도 상관 없기 때문에 실제로는 거의 사용하지 않는다.


     

     

     

    4. 스레드 라이브러리


    스레드 라이브러리는 프로그래머에게 스레드를 생성하고 관리하기 위한 API를 제공한다.

     

    스레드 라이브러리를 구현하는 방법

    • 커널의 지원 없이 완전히 사용자 공간에서만 라이브러리를 제공하는 것. 이때 라이브러리 함수를 호출하면 사용자 공간의 지역 함수를 호출한다.
    • 운영체제에 의해 지원되는 커널 수준 라이브러리를 구현하는 것. 이때 라이브러리 함수를 호출하면 시스템 콜을 호출한다.

    다수의 스레드를 생성하는 방법은 비동기 스레딩과 동기 스레딩으로 나뉜다.

    비동기 스레딩은 부모가 자식 스레드를 생성한 후 부모는 자신의 실행을 재개하여 부모와 자식 스레드가 서로 독립적으로 병행하게 실행된다. 서로 독립적이기 때문에 부모와 자식 사이에 데이터 공유는 거의 없다.

    동기 스레딩은 부모 스레드가 하나 이상의 자식 스레드를 생성하고, 부모 스레드는 자식 스레드 모두가 종료할 때까지 기다리다가 자신의 실행을 재개하는 방식이다. 자식들은 서로 병행하게 실행할 수 있고, 상당한 데이터 공유를 수반한다.


     

     

     

    5. 암묵적 스레딩


    다중 코어 처리의 성장으로 인해 수천개의 스레드를 가진 응용 프로그램이 등장하게 되었다. 이것을 설계하는 것이 어렵기 때문에 암묵적 스레딩이라는 전략을 사용하고 있다.

    암묵적 스레딩이란 스레딩의 생성과 관리 책임을 개발자로부터 컴파일러와 실행시간 라이브러리에게 넘겨주는 것이다.


    1) 스레드 풀

    개요에서 언급했듯이 웹 서버는 요청을 받을 때마다 그 요청을 위해 새로운 스레드를 생성하는데, 새로운 스레드를 계속 만들어내는 것은 문제가 있다.

     

    - 스레드를 생성할 때마다 시간이 소요된다.

    - 스레드를 몇 개까지 생성할 수 있는지 한계가 정해져 있지 않다.

     

    스레드 풀의 기본 아이디어는 프로세스를 시작할 때 아예 일정한 수의 스레드들을 미리 풀로 만들어두는 것이다. 여기에 있는 스레드들은 대기하다가, 서버가 요청을 받으면 스레드 풀에 요청을 제출하여 스레드를 받는다. 이때 서비스를 완료하면 스레드는 다시 스레드 풀로 돌아간다.

     

    스레드 풀의 장점

    - 스레드를 새로 생성하는 것보다 더 빠르다.

    - 스레드 풀은 임의 시각에 존재할 스레드 개수에 제한을 둔다. 이런 제한은 많은 수의 스레드를 병렬 처리할 수 없는 시스템에 도움이 된다.

    - 태스크를 생성하는 방법을 태스크로부터 분리하면 태스크 실행을 태스크 생성과 시간을 다르게 할 수 있다.


     

    반응형

    '공부 > 운영체제(OS)' 카테고리의 다른 글

    [공룡책] Ch.6 동기화 도구  (0) 2022.04.27
    [공룡책] Ch 5. CPU 스케줄링  (0) 2022.04.27
    [공룡책] Ch 3. 프로세스  (0) 2022.04.26
    [공룡책] Ch 2. 운영체제 구조  (0) 2022.04.19
    [공룡책] Ch 1. 서론  (0) 2022.04.12

    댓글

Designed by Tistory.