본문 바로가기
Programming/C | C++

OpenMP(2) - 입문자용 주요 사용법 간단한 설명/정리(omp single, master, task, taskwait, barrier)

by 썽하 2020. 7. 31.

 

저번 글에 이어서 몇 가지 더 사용법 정리.

 


 

사용법

1. omp single

#pragma omp single // 하나의 thread만 실행한다. 다른 thread는 기다린다.
#pragma omp single nowait // 하나의 thread만 실행한다. 다른 thread는 기다리지 않는다.

하나의 쓰레드만 동작하게 한다. 초기화나 출력부처럼 병렬 처리가 필요 없는 부분에서 용이하다.

 

int sum;
#pragma omp parallel
{
// 초기화는 하나의 thread만 해도된다.
#pragma omp single nowait
{
sum = 0 ;
}
#pragma omp for
for(int i = 0 ;i < 10 ;i++)
{
printf("thread %d calc sum\n", omp_get_thread_num());
#pragma atomic
sum += i;
}
// 출력은 하나의 thread만 해도된다.
#pragma omp single
{
printf("thread %d init sum : %d\n", omp_get_thread_num(), sum);
}
// 다시 병렬로 작업을 한다.
printf("thread %d done\n", omp_get_thread_num());
}
/*
thread 0 calc sum
thread 0 calc sum
thread 0 calc sum
thread 2 calc sum
thread 2 calc sum
thread 3 calc sum
thread 3 calc sum
thread 1 calc sum
thread 1 calc sum
thread 1 calc sum
thread 0 init sum : 45
thread 0 done
thread 3 done
thread 2 done
thread 1 done
*/
view raw omp_single.cpp hosted with ❤ by GitHub

2. omp master

#pragma omp master // master thread만 실행한다. 다른 thread는 기다리지 않고 넘어간다.

single과 매우 유사하지만 master thread 하나만 동작한다. 또한, 다른 쓰레드는 기다리지 않고 다음 부분을 실행한다.

3. omp task

#pragma omp task // thread 하나에 task를 넘겨주고 넘어간다.

다음에 오는 코드를 다른 하나의 thread에 넘겨주고 넘어간다.

 

const int N = 10;
int partialSum[N] ={0,};
#pragma omp parallel shared(partialSum)
#pragma omp single
{
for (int i = 0 ; i < N ; i++)
{
#pragma omp task // 쓰레드 하나에 다음 job을 던져주고 넘어간다.
{
partialSum[i] = do_something(i * 1000);
printf("thread %d partial sum : %d\n", omp_get_thread_num(), partialSum[i]);
}
}
int totalSum = 0;
for (int i = 0 ; i < N ; i++)
totalSum += partialSum[i];
printf("thread %d total sum : %d\n", omp_get_thread_num(), totalSum);
}
/*
// task를 기다리지 않기 때문에 partialSum이 계산 되기전에 total sum이 계산 되어버린다.
thread 17 total sum : 0
thread 1 partial sum : 0
thread 4 partial sum : 4953750
thread 6 partial sum : 34881906
thread 12 partial sum : 29962675
thread 13 partial sum : 9817987
thread 22 partial sum : 39995308
thread 2 partial sum : 15164899
thread 23 partial sum : 20087192
thread 20 partial sum : 24987327
thread 11 partial sum : 45058713
*/
view raw omp_task.cpp hosted with ❤ by GitHub

4. omp taskwait

#pragma omp taskwait // 이전에 발생된 task가 모두 완료되고 난뒤 다음 행에 진입한다.

task들이 모두 완료될 때까지 동기화가 필요할 때가 있다. 그럴 때 taskwait를 써서 완료되지 않은 thread를 기다려 줄 수 있다.

 

const int N = 10;
int partialSum[N] ={0,};
#pragma omp parallel shared(partialSum)
#pragma omp single
{
for (int i = 0 ; i < N ; i++)
{
#pragma omp task
{
partialSum[i] = do_something(i * 1000);
printf("thread %d partial sum : %d\n", omp_get_thread_num(), partialSum[i]);
}
}
#pragma omp taskwait // 위에서 생성된 task가 모두 종료 될 때까지 기다린다.
int totalSum = 0;
for (int i = 0 ; i < N ; i++)
totalSum += partialSum[i];
printf("thread %d total sum : %d\n", omp_get_thread_num(), totalSum);
}
/*
thread 4 partial sum : 0
thread 19 partial sum : 9989625
thread 23 partial sum : 4944948
thread 12 partial sum : 20006788
thread 3 partial sum : 25184388
thread 0 partial sum : 15051329
thread 6 partial sum : 30223360
thread 21 partial sum : 45053433
thread 1 partial sum : 35240305
thread 15 partial sum : 39894532
thread 21 total sum : 225588708 // 이상없이 total sum이 출력된다.
*/

5. omp barrier

#pragma omp barrier // 모든 thread가 barrier에 도착한 후 이후 라인을 실행한다.

딥러닝 같이 task들의 stage가 명확하게 구분되어있고 이전 stage가 완료되어야만 다음 stage를 실행할 수 있는 경우 barrier로 먼저 끝난 thread를 기다리게 할 수 있다.

 

void do_precondition()
{
printf("thread %d do precondtition\n", omp_get_thread_num());
}
void do_main_work()
{
printf("thread %d do main work\n", omp_get_thread_num());
}
void do_job()
{
do_precondition(); // 모든 thread가 precondition을 실행한 후
#pragma omp barrier
do_main_work(); // main work 를 실행한다.
}
int main()
{
#pragma omp parallel for num_threads(4)
for(int i = 0; i < 4; i++)
do_job();
return 0;
}
/*
thread 0 do precondtition
thread 2 do precondtition
thread 3 do precondtition
thread 1 do precondtition
thread 1 do main work
thread 3 do main work
thread 0 do main work
thread 2 do main work
*/
view raw omp_barrier.cpp hosted with ❤ by GitHub

 

Reference

 


 

데이터 동기화나 task 쪽에 자주 쓰는 것들을 정리해보았다.

 

댓글