1. Collapse
개요
#pragma omp for collapse(loop 개수)
로 정의 후 사용중첩 loop문
#pragma omp for
사용: syntax error2. Example
C code
#include <stdio.h>
#include <omp.h>
#define N 10000
int main()
{
int a[N][N], i, j;
omp_set_num_threads(4);
#pragma omp parallel for private(i,j) collapse(2)
for (i=0; i<N; i++)
for (j=0; j<N; j++)
a[i][j] *= 2;
}
사용
#pragma omp parallel for collapse()
선언1. Example (Flush)
C code
#include <stdio.h>
#include <omp.h>
#include <unistd.h>
int main()
{
int x=0;tid;
omp_set_num_threads(4);
#pragma omp parallel private(tid)
{
tid=omp_get_thread_num();
if (tid==0) {
sleep(3);
x=1;
sleep(3);
}
while (x==0) {
}
printf("x=%d in %d-th thread\n",x,tid);
}
}
Result
-O3
최적화 옵션을 넣은 경우, while문을 스레드 1~3이 빠져나오지 못함해석
-O3
옵션은 성능 향상을 위해 x를 캐시에 저장해두고 읽기 때문에 메모리에서의 x 변화를 인지하지 못함2. Flush
FLUSH Directive
사용
while (x==0) {
#pragma omp flush(x)
}
#pragma omp flush(x)
사용 후 컴파일 시, 스레드 1~3이 정상적으로 while문 탈출3. False Sharing
원인
해결
4. Example 1 (False Sharing)
C code
#include <stdio.h>
#include <omp.h>
#define N 10000000
int main()
{
long sum=0; a[4]={0}, i, tid;
omp_set_num_threads(4);
#pragma omp parallel private(tid)
{
tid=omp_get_thread_num();
#pragma omp for
for (i=1; i<=N; i++)
a[tid]+=i;
#pragma omp atomic
sum += a[tid];
}
printf("sum = %ld\n",sum);
}
Result
4. Example 2 (False Sharing Avoidance)
C code
#include <stdio.h>
#include <omp.h>
#define N 10000000
int main()
{
long sum=0; a[4*8]={0}, i, tid;
omp_set_num_threads(4);
#pragma omp parallel private(tid)
{
tid=omp_get_thread_num();
#pragma omp for
for (i=1; i<=N; i++)
a[tid*8]+=i;
#pragma omp atomic
sum += a[tid*8];
}
printf("sum = %ld\n",sum);
}
Result
1. 데이터 의존성
개요
대상
2. Loop-carried 의존성
flow 의존성(true dependence or RAW)
anti 의존성
output 의존성
3. Example (Loop Carried 의존성)
C code
for (i=0; i<N; i++)
x = d[i] + 1
a[i] = a[i+1] + x
b[i] = b[i] + b[i-1] + d[i-1]
c[2] = 2*i
해석
4. 데이터 의존성의 제거
의존성 제거
주의