OpenMP Basic II - 동기화 및 Critical, Atomic, Barrier

GraGrass·2024년 1월 18일
0

Chapter 5

동기화

1. 동기화

Synchronization

  • 스레드에 할당된 작업 실행 순서에 제한을 둘 수 있음
  • 공유 데이터에 대한 접근을 제어

고 수준 동기화

  • critical, atomic, barrier, ordered

저 수준 동기화

  • flush, locks

2. critical vs atomic

critical

  • 한번에 하나의 스레드만이 이름으로 구분되는 critical 영역에 진입

atomic

  • 한 메모리 위치에만 적용됨. mini-critical section 역할

Critical, Atomic, Barrier

1. critical

한 객체에 하나의 스레드

  • #pragma omp critical [크리티컬 객체 이름] 형식으로 지정 사용
  • 같은 크리티컬 객체 명으로 지정된 경우 영역은 한번에 하나의 스레드만 실행
  • 다른 스레드가 같은 이름의 크리티컬 객체 사용시, 먼저 실행한 스레드 동작 완료까지 진입 시점에서 대기
  • atomic 지시어로 지정할 수 없던 수식도 critical 영역으로 지정 가능

2. atomic

RW 동시 수행 작업

  • #pragma omp atomic 형식으로 지정 사용
  • 여러 개의 스레드가 하나의 공유 변수를 동시에 변경할 때 발생하는 경쟁상태 방지
  • 공유변수에 대해, 읽기/쓰기가 한번에 이루어지는 연산자에서만 사용
  • +, -, *, /, &, |, ^, <<, >> 연산자일 경우 사용 가능
  • atomic 구문에서는 {중괄호} 사용 불가

데이터 레이싱

  • 같은 변수에 대한 R,W 작업 동시 수행시 발생
  • Write한 값이 씹히거나, 이상한 값을 Read하거나 하는 현상이 발생

3. barrier

스레드 체크포인트

  • 모든 스레드들이 barrier에 도달할 때 까지 대기
  • 스레드팀의 모든 스레드 동기화
  • 작업 분할 구분 내에서 사용 불가
    ex. if, while, for, switch
  • barrier가 if문 안에 들어가는 경우, Deadlock이 걸릴 수 있음

Example

#include <stdio.h>
#include <omp.h>

int main()
{
	int x=1;
    omp_set_num_threads(4);
#pragma omp parallel shared(x)
{
	x++;
#pragma omp barrier
	printf("x= %d\n",x);
}
}
  • 4개의 스레드가 x++ 수행할 때 까지 printf() 수행 X
  • 모두 x=5가 출력될 것

Inner Product (개선)

1. C code

#include <stdio.h>
#include <omp.h>
#define N 10000

int main()
{
	long int i, sum=0, local_sum=0;
    int a[N], b[N];
    double stime, etime;
    
    for(i=0; i<N; i++){
    	a[i]=i+1;
        b[i]=i+2;
        }
        
	stime=omp_get_wtime();
#pragma omp parallel private(local_sum)
{
	local_sum=0;
    #pragma omp for
    for(i=0; i<N; i++)
    	local_sum+=a[i]*b[i];
	#pragma omp atomic
    sum+=local_sum;
}       
    // inner product for loop의 소요시간 = etime
    etime=omp_get_wtime()-stime;
    printf("sum= %ld\n", sum);
    printf("Elapsed Time= %lf\n", etime);
}

local_sum

  • private var local_sum 사용
  • 각 스레드에서 local_sum을 루프 병렬화를 통해 구함

sum

  • global var sum
  • atomic 동기화된 작업 sum+=local_sum;으로 각 스레드에서의 계산값을 취합

2. Result

serial inner product

  • 1.6초 정도 소요

parallel inner product

  • 0.3초 정도 소요
  • serial code에 비해 확실히 빠름
  • 단, atomic/critial 동기화가 for 루프 내에 쓰인다면 매우 느려질 수 있으니 주의
profile
올해는 진짜 갓생 산다

0개의 댓글