스레드는 CPU 이용의 기본 단위이다.
스레드는 스레드 ID, 프로그램 카운터 (PC), 레지스터, 스택으로 구성
스레드는 같은 프로세스에 속한 다른 스레드와 공유를 할 수 있다.
다중 스레드에서 스레드 각각 레지스터, 스택, PC를 가지고 코드 데이터 파일은 공유를 한다.
이미지 모음에서 사진 축소판을 만드는 응용 프로그램은 별도의 스레드를 사용하여 개별 이미지에서 축소판을 생성할 수 있다.
하나의 스레드가 이미지를 표시하고 다른 스레드는 네트워크에서 데이터를 검색하도록 할 수 있다.
그래픽을 표시하는 스레드, 키 입력에 응답하는 스레드, 맞춤법을 검사하는 스레드
다수의 CPU 집중 작업을 병렬로 처리할 수 있다.
대부분의 운영체제 커널도 일반적으로 다중 스레드이다.
리눅스 시스템에서 시스템을 부트하는 동안 여러 커널 스레드가 생성된다.
각 스레드는 장치 관리, 메모리 관리 등 특정 작업을 수행한다.
멀티쓰레딩 프로그래밍의 이점
응답성 : 단일 스레드이면 처리시간이 느린 작업을 완료할 떄까지 대기해야 하지만, 멀티스레드이면 또 다른 수행처리를 할 수 있어서 응답성이 높다.
자원 공유 : 프로세스는 공유 메모리와 메시지 전달 기법을 통해서 자원을 공유할 수 있지만, 스레드는 프로세스의 자원들과 메모리를 공유한다. 같은 주소 공간 내에 여러 개의 다른 작업을 하는 스레드를 가질 수 있다.
경제성 : 프로세스 생성은 메모리 자원을 많이 쓴다.
규모 적응성 : 다중 처리기 구조에서 각각의 스레드가 다른 처리기에서 병렬로 수행될 수 있다. 처리하는 규모가 더 많아짐
멀티코어에서는 각 코어에 별도의 스레드를 할당할 수 있어서 병렬로 실행가능
병행 시스템은 모든 작업이 진행되게 하여 둘 이상의 작업을 지원
병렬 시스템은 둘 이상의 작업을 동시에 수행할 수 있다.
Amdahl's Law : 4개의 코어가 4배의 효율은 아님. 약 2.5배
태스크 인식 : 응용을 분석하여 독립된 병행 가능 태스크로 나눌 수 있는 영역을 찾는 작업이 필요, 태스크는 서로 독립적이고 개별 코어에서 병렬 실행될 수 있어야 함
균형 : 병렬로 실행될 수 있는 태스크들이 전체 작업에 균등한 기여도를 가지도록 태스크로 나누는 것도 매우 중요.
데이터 분리 : 태스크가 접근하고 조작하는 데이터 또한 개별 코어에서 사용할 수 있도록 나누어져야 한다.
데이터 종속성 : 둘 이상의 태스크에 종속성이 없어야 한다.
시험 및 디버깅 : 멀티 스레딩 프로그래밍의 오류란 잡기 되게 어렵다.
데이터 병렬 실행 : 동일한 데이터의 부분집합을 다수의 계산 코어에 분배한 뒤 각 코어에서 동일한 연산을 실행
테스크 병렬 실행 : 스레드를 다수의 코어에 분배, 각 스레드는 고유의 연산을 실행한다. 스레드들은 동일한 데이터, 다른 데이터에 연산을 실행할 수 있다.
데이터 병렬 처리는 데이터에 여러 코어를 배분하고, 태스크 병렬 처리는 여러 코어에 태스크를 분배하는 것이다.
스레드를 위한 지원은 사용자 스레드를 위해서는 사용자 수준에서, 커널 스레드를 위해서는 커널 수준에서 제공된다.
사용자 스레드는 커널 위에서 지원되며, 커널의 지원 없이 관리된다.
커널 스레드는 운영체제에 의해 직접 지원되고 관리된다.
여러 사용자 스레드가 하나의 커널 스레드로 연결된다.
한 스레드가 봉쇄형 시스템 콜을 하면, 전체 프로세스가 봉쇄된다.
또한, 한번에 하나의 스레드만 커널에 접근할 수 있어서 멀티 스레드가 멀티 코어 시스템에서 병렬로 실행 x
하나의 스레드가 봉쇄형 시스템 콜을 불러도 다른 스레드가 커널에 접근가능, 더 많은 병렬성 제공
대신 커널 스레드를 많이 만들어야하는 단점이 있음
사용자 스레드 수보다 작거나 같은 수의 커널 스레드를 만드는 것
커널 스레드의 수는 응용 프로그램이나 특정 기계에 따라 결정
필요한 만큼 사용자 수준 스레드를 생성할 수 있고 다중 처리기에서 병렬로 수행 가능, 봉쇄형 시스템 콜 사용 가능
두 수준 모델
한 사용자 스레드가 하나의 커널 스레드에만 연관된 것 + 기존 다대다 모델
구현 어렵, 코어 수가 증가함에 따라 커널 스레드 수를 제한할 필요가 없음.
따라서 요샌 일대일 모델을 많이 씀
스레드 라이브러리는 프로그래머에게 스레드를 생성하고 관리하기 위한 API
커널의 지원 없이 완전히 사용자 공간에서만 라이브러리를 제공하는 것, 라이브러리 함수를 호출하는 것은 시스템 콜이 아니라 사용자 공간의 지역 함수를 호출하게 된다는 것
운영체제에 의해 지원되는 커널 수준 라이브러리를 구현하는 것 (Pthread 같은 것)
비동기 스레딩은 부모와 자식 스레드가 독립적으로 병행하게 실행, 데이터 공유는 거의 없음
동기스레딩은 자식 스레드 모두가 종료할때까지 부모는 기다렸다가 자신을 실행함, 자식 스레드들은 병행하게 실행하지만, 부모는 자식들의 작업이 끝날 때까지 실행을 할 수 없다. 데이터 공유가 많음
pthreads는 스레드 생성과 동기화를 위해 제정한 표준 API
스레딩의 생성과 관리 책임을 응용 개발자로부터 컴파일러와 실행 시간 라이브러리에게 넘겨주는 것> 암묵적 스레딩
암묵적 스레딩은 병렬로 실행할 수 있는 스레드가 아닌 것을 식별해야함
런타임 라이브러리는 일반적으로 다대다 모델을 사용
병렬 작업만 식별하고, 라이브러리는 스레드 생성 및 관리에 대한 특정 세부 사항을 결정한다
스레드를 매번 생성하는데 시간이 들고, 또 얼만큼 만들 수 있는지에 대한 한계를 정해야 하는데 이때 사용되는 방법이 스레드 풀이다.
일정한 수의 스레드를 미리 생성하고, 요청을 받으면 즉시 서비스가 되는 것이다.
만약 스레드가 없으면, 기다려야함
스레드 풀에 있는 스레드의 개수는 CPU 수, 요청 수에 따라 정해지고, 풀의 활용도를 보며 동적으로 풀의 크기도 변형 간으
fork join 메소드를 사용하면 메인 부모 스레드가 하나 이상의 자식 스레드를 생성한 다음 자식의 종료를 기다린 후 join하고 그 시점부터 자식의 결과를 확인하고 결합할 수 있다.
OpenMP는 c,C++로 작성된 API와 컴파일러 디렉티브의 집합이다.
공유 메모리 환경에서 병렬 프로그래밍을 할 수 있도록 도움을 준다.
병렬로 실행할 수 있는 블록을 찾아 병렬 영역이락 부른다.
fork는 프로세스를 생성하는 시스템 콜 함수이다.
한 프로그램의 스레드가 fork를 호출하면 새로운 프로세스는 모든 스레드를 복제해야 하는가? 아니면 한 개의 스레드만 가지는 프로세스인가를 결정해야한다.
exec를 부르면 exec의 매개변수로 지정된 프로그램이 모든 스레드를 포함한 전체 프로세스를 대체시킨다.
두 버전의 fork중 어느쪽을 택하는지는 응용 프로그램에 달려있음
1. fork를 부르자마자 다시 exec를 부른다면 모든 스레드를 복제해서 만드는 것은 불필요한 작업 (exec가 모든 것을 다시 대체하기 때문)
2. fork 후 exec를 하지 않는다면 새 프로세스는 모든 스레드들을 복제해야 한다.
신호는 프로세스에서 어떤 이벤트가 일어났음을 알려주기 위해 사용됨
동기식, 비동기식
동기식 신호는 불법적인 메모리 접근, 0으로 나누기가 있음
동기식 신호는 신호를 발생시킨 연산을 한 동일한 프로세스에 전달됨
외부로부터 발생하면 그 프로세스는 신호를 비동기식으로 전달 받는다.
(Control c)
모든 신호는 디폴트 신호 처리기, 사용자 정의 신호 처리기에 의해 처리됨
멀티 스레드의 경우 복잡
1. 신호가 적용될 스레드에게 전달
2. 모든 스레드에게 전달
3. 몇몇 스레드들에만 선택적으로 전달
4. 특정 스레드가 모든 신호를 전달
신호 유형에 따라 4가지 방법 중 1개를 택하자
동기식 신호는 그 신호를 야기한 스레드에게 전달되어야 하고, 다른 스레드들에게 전달되면 안됨
비동기식 신호는 명확하지 않음, Control c는 모든 스레드에게 전달되어야함
kill은 신호를 전달하는데 사용되며, 전달될 PID를 지정한다.
멀티 스레드에서는 받아들일 신호와 봉쇄할 신호를 지정할 수 있고, 비동기식 신호를 봉쇄하지 않고 있는 스레드들에게만 신호를 전달할 수도 있다.
하지만 신호는 한번만 전달되므로, 봉쇄하고 있지 않는 첫번쨰 스레드에게만 신호가 전달된다.
스레드 취소는 스레드가 끝나기 전에 그것을 강제 종료시키는 작업
웹 브라우저에서 각 이미지는 여러 스레드에의해 적재되는데 웹 창을 닫으면 모든 스레드가 취소된다.
취소되어야 할 스레드를 목적 스레드라고 한다!
비동기식 취소를 할때 조심해야함
비동기식 취소를 할때 모든 시스템 자원을 회수하지 못하고 취소하면, 필요한 시스템 자원을 다 사용가능한 상태로 만들지 못할 수 있다.
지연취소의 경우에는 한 스레드가 목적 스레드를 취소해야 한다고 표시하지만 실제 취소는 목적 스레드가 취소 여부를 결정하기 위한 플래그를 검사한 이후에야 일어남
Pthread_cancel을호출하면 대상 스레드를 취소하라는 요청만 표시된다.
실제 취소는 욫ㅇ을 처리하기 위해 대상 스레드가 설정되는 방식에 달려있다. 취소가되면 join 호출이 반환됨
기본 취소 유형은 지연취소이다. 그러나 스레드가 취소점에 도달한 경우에만 취소가 발생한다.
Pthreads는 스레드가 취소될 때 정리 핸들러라고 하는 함수가 호출되게 할 수 있다.
스레드가 종료되기 전에 스레드가 획득한 모든 자원을 해제할 수 있다.
한 프로세스에 속한 스레드들은 프로세스의 데이터를 모두 공유한다.
상황에 따라선 공유를 하지 않을때도 있어야함
이런 데이터를 스레드 로컬 저장장치 TLS라고 부른다.
TLS 데이터는 스레드마다 고유하므로 정적 데이터와 유사하다.
스레드 라이브러리와 커널의 통신문제, 다대다 모델에서 해결해야 함
커널의 수를 동적으로 조절이 가능함
다대다 모델은 커널과 사용자 사이에 경량 프로세스 LWP라는 자료구조를 둔다.
LWP는 하나의 커널 스레드에 부속되어 있으며 물리 처리기에서 스케줄하는 대상은 바로 커널 스레드이다.
입출력이 완료되기를 기다리는 동안 커널 스레드가 봉쇄되면 LWP도 같이 봉쇄된다.
5개의 입출력이 있으면 LWP도 5개 있어야함. 그렇지 않으면 한개의 LWP가 끝날때까지 대기
사용자 스레드 라이브러리와 커널 스레드 간의 통신 방법은 스케줄러 액티베이션 방법을 사용한다.
커널은 응용에 가상처리기(LWP) 집합을 제공하고 응용은 사용자 스레드를 가용한 가상 처리기로 스케줄한다.
커널은 응용에게 특정 이벤트에 대해 알려줘야 함
이 프로시저를 upcall이라하고, upcall은 upcall 처리기에 의해 처리되고, upcall 처리기는 가상 처리기상에서 실행되어야한다.
스레드는 CPU 사용의 기본단위를 나타내며 동일한 프로세스에 속하는 스레드는 코드 및 데이터를 포함하여 많은 프로세스 자원을 공유한다.
다중 스레드 응용 프로그램은 응답성, 자원 공유, 경제성,확장성의 이점이 있다.
단일 CPU에서는 병행성, 병렬성은 여러 CPU를 제공하는 다중 코어 시스템이 필요
멀티 스레드 프로그램은 작업 분할 및 균형 조정, 데이터 분할 및 데이터 종속성 식별, 디버깅 어려움 등의 문제가 있다.
데이터 병렬 처리는 동일한 데이터의 부분 집합을 다른 컴퓨팅 코어에 분산시키고 각 코어에서 동일한 연산을 수행한다. 작업 병렬 처리는 여러 코어에 데이터가 아니라 작업을 분산시킨다.
사용자 응용 프로그램은 사용자 수준 스레드를 생성하며, 스레드는 궁극적으로 CPU에서 실행되도록 커널 스레드에 매핑되어야 한다.
스레드 라이브러리는 스레드를 만들고 관리하기 위한 API를 제공한다.
암묵적 스레딩에는 스레드가 아니라 작업을 식별하고 언어 또는 API 프레임 워크가 스레드를 만들고 관리할 수 있게 한다.
스레드는 비동기 또는 지연 취소를 사용하여 종료될 수 있다.