본문 바로가기

Programming/OpenMP

OpenMP 스레드 메모리 공간 이해하기

  • 스레드 메모리 공간


각각의 객체는 고유한 메모리 영역을 가지게 된다. 클래스, 글로벌, 정적변수, 동적 메모리와 같이 다양한 객체들이 자신들 변수를 소유한다. OpenMP가 지원하는 스레드들도 각각의 고유한 메모리 영역을 가지게 되는데, 이것을 잘 구분해야만 병렬처리를 하면서 작업을 배분하거나 결과를 얻어낼 때 데이터 경쟁 같은 오류를 막을 수 있다.


공유 메모리 영역

#pragma omp parallel 지시어 영역 밖에 있는 메모리 변수는 생성된 스레드가 공유할 수 있다. 모든 스레드가 읽고 쓰기를 할 수 있다고 하여 공유 메모리(shared)변수라고 한다. 만일 2개의 스레드가 하나의 변수의 값을 수정하면 어떻게 동작하게 될지 살펴보자.


0으로 초기화 된 공유 메모리 변수 x가 있다. 0번 스레드가 x 의 값을 1로 변경하였다. 이후에 1번 스레드가 2라고 값을 변경하고 병렬영역이 종료된 후에 값 x는 2로 변하게 된다. 모두가 접근할 수 있기 때문에 마지막에 작성한 값이 계속 남아있게 된다.


이처럼 공유 메모리 변수에 대해 스레드 간의 입출력으로 발생하는 오류를 경쟁상태라고 한다. 

경쟁상태는 병렬프로그램에서 공유 메모리 변수를 잘못 사용함으로 인해 생기는 버그이다. 사실 변수의 잘못된 사용이라기 보다는 병렬프로그램을 잘못 설계하여 발생하는 버그에 가까운데 경쟁상태가 발생하면 심각함 오류를 발생시키고 디버그하기도 어렵다.


해당 변수에 대해 여러 스레드가 읽고 쓰기 위해서 경쟁하는 것을 막기 위해 개별 스레드가 소유하는 메모리 변수를 할당하거나 동기화 처리를 하기 된다.


공유메모리의 사용

#include "stdafx.h"

#include "omp.h"


int _tmain(int argc, _TCHAR* argv[])

{

int x = 0;

printf("main area x : %d\n", x);

}


#pragma omp parallel

{

if( omp_get_thread_num() == 0)

x = 1;

else

x = 2;


printf("Num %d thread area x : %d\n", omp_get_thread_num(), x);

}


printf("main area x : %d\n", x);


return 0;

}


결과

main area x : 0

Num 0 thread area x : 1

Num 1 thread area x : 2

main area x : 2

처음에 선언한 변수 x는 main 스레드의 소유이다. main 스레드 변수는 기본적으로 공유 가능한 메모리 변수로 OpenMP에서 생성한 스레드에서 읽고 쓰기가 가능하다.


1. #pragma omp parallel 지시어로 쿼드코어 CPU에서 4개의 스레드가 생성된다.

2. 0번 스레드는 공유 메모리 변수 x에 대해서 1로 변경하고 그 값을 출력한다.

3. 1번 스레드는 공유 메모리 변수 x에 대해서 2로 변경하고 그 값을 출력한다.


스레드 프라이빗 변수


스레드 프라이빗 지정

#include "stdafx.h"

#include "omp.h"


int _tmain(int argc, _TCHAR* argv[])

{

int x = 0;

printf("main area x : %d\n", x);

}


#pragma omp parallel private(x) // 프라이빗 보조지시어 사용

{

if( omp_get_thread_num() == 0)

x = 1;

else

x = 2;


printf("Num %d thread area x : %d\n", omp_get_thread_num(), x);

}


printf("main area x : %d\n", x);


return 0;

}


결과

main area x : 0

Num 0 thread area x : 1

Num 1 thread area x : 2

main area x : 0





반응형
LIST