암묵적 쓰레딩이란?
쓰레딩을 프로그래머가 직접하지 않고, 커널이 하게 두는 것.
- 쓰레드 대신 task에 대한 정의만 해주면 된다.
책에서는 5가지 방법을 소개했다.
- Thread pool
- Fork join (자바)
- OpenMP (C, C++)
- Grand central patch (애플)
- Thread Building Blocks (인텔)
Thread pool
다중 쓰레드 만들기의 문제점
- 쓰레드 생성 시 걸리는 시간
- 시스템에서 동시에 실행할 수 있는 쓰레드의 갯수
그래서 나온 아이디어 중 하나 = 쓰레드 풀
- 일정한 수의 쓰레드를 미리 만들자는 전략
- 쓰레드가 필요하면 이미 만들어진 쓰레드를 즉시 서비스
- 서비스 완료 시 다시 쓰레드 풀로 돌아감.
장점
- 기존 쓰레드로 서비스하는 것이 더 빠르다.
- 존재할 수 있는 쓰레드 갯수에 제한을 둬서 시스템 과부하를 막는다.
- 태스크를 만드는 것과 태스크를 실행하는 것을 분리. (앞 단원 참고)
- 태스크를 일정 시간 이후에 실행시킬 수 있음.
예시
windows에서는 다음과 같은 함수들을 제공한다.
c
DWORD WINAPI PoolFunction(PVOID param) {…} // 쓰레드에서 실행할 함수
QueueUserWorkItem(&PoolFunction, NULL, 0);
// 쓰레드 풀 속 쓰레드 중 하나가 PoolFunction을
// 파라미터 'NULL'을 받으면서,
// 생성 및 관리할 플래그로 '0'을 선정해
// 실행한다.
java.util.concurrent 패키지에선 다음 함수를 제공한다.
Executor.newSingleThreadExecutor(): 크기가 1인 풀 = 1개의 쓰레드 생성Executor.newFixedThreadExecutor(int size): 크기가size인 풀 =size개의 쓰레드 생성Executor.newCachedThreadPool(): 크기가 무제한인 풀 생성
Fork join (java)
- 4.4장에서 다뤘던 동기식 방식과 같다.
- fork → 자식 쓰레드 처리 → 자식 쓰레드 반환 → 부모 쓰레드 실행 → 종료
자바에서는 어떻게 암시적으로 동기적 방식을 다루는지 알아보자.
java
import java.util.concurrent.*;
class Sum implements extends RecursiveTask<Integer>
{
static final int THRESHOLD = 1000;
private int begin;
private int end;
private int[] array;
public Sum(int begin, int end, int[] array) {
this.begin = begin;
this.end = end;
this.array = array;
}
protected Integer compute() {
if (end - begin < THRESHOLD) {
// 쓰레드가 적을때
int sum = 0;
for (int i = begin; i < end; i++)
sum += array[i];
return sum;
}
else {
// 쓰레드가 많을때
int mid = (begin + end) / 2;
Sum left = new Sum(begin, mid, array);
Sum right = new Sum(begin, mid, array);
left.fork();
right.fork();
return right.join() + left.join(); // join으로 결과 반환
}
}
}
public class thread {
public static void main(String args[]) {
int num = Integer.parseInt(args[0].trim);
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < num; i++)
pool.execute(new Task()); // 쓰레드 'num'개 생성 및 실행
pool.shutdown() // 모든 쓰레드들을 한꺼번에 종료
}
}
OpenMP
c, cpp로 작성된 API와 컴파일러 디렉티브의 집합.
공유 메모리 환경에서 병렬 프로그래밍을 할 수 있게 도움을 줌.
- 병렬로 실행될 수 있는 블록을 병렬 영역이라고 부름.
c
컴파일러와 물려서 쓰는 것
Grand central patch (by Apple)
병렬로 실행될 태스크를 식별할 수 있도록 하는 API, 런타임 라이브러리 등의 조합.
- 태스크를 디스패치 큐에 넣어서 스케줄 함.
- GCD는 직렬과 병행 2가지 유형의 디스패치 큐를 유지
thread-building block (by Intel)
C++에서 병렬 응용 프로그램 설계를 지원하는 템플릿 라이브러리.