티스토리 뷰

인텔이 넷버스트 아키텍쳐를 버리고 코어 마이크로 아키텍쳐로 cpu의 역사를 새로 쓴 이 시점에서, 콘로와 켄츠필드는 더 이상 싱글스레드only 프로그램은 있을 수 없다는 것을 아주 정확히 말해준다.

OpenMP는 smp(symmetric multi processing)용 api중 하나이다. 언어는 포트란과 C/C++을 지원한다. 아래의 링크는 OpenMP에 대한 간략한 설명이다.

http://en.wikipedia.org/wiki/Openmp

openmp를 이용하면 노가다로 스레드를 만들어서 하는 멀티프로세싱과는 다르게, 기존의 순차 코드에 omp를 적용해서 자동??으로 어느정도의 패러럴 프로세싱을 할 수 있다.

예를들어, 아래의 포문에 진입하게되면 코어 개수에 맞춰서(혹은 설정값대로)스레드가 생성되어 패러럴하게 for문을 진행한다. 정확한 동작은 알 수 없으나 아마 스레드가 2개라면 홀수-짝수순으로 진행할 것이다.

    24:   sum = 0;
    25: #pragma omp parallel for reduction(+: sum)
    26:   for (i = 0; i<NUM_STEPS; i++) {
    27:     x = 2.0 * (double)i / (double)(NUM_STEPS); /* value of x */
    28:     sum += x * x / NUM_STEPS;
    29:   }

openmp는 vc에 디폴트로 탑재되어 있고 smp관련 api중 쓰기가 편하다고 한다.

아직 멀티 프로세싱이 활성화가 안되서 그런지, 적절한 자료를 찾기가 힘들었지만 지금껏 본것 중 가장 쉬운 튜토리얼을 소개한다.

http://www.kallipolis.com/openmp/

내가 여기서 말하고자 하는건 openmp가 만능일 순 없다는 것이다. 사실 튜토리얼만 따라가봐도 openmp가 얼마나 쓰기 불안하고 애매한지 알 수 있다. 위의 코드를 다시 예로 들어보자. 패러럴하게 계산을 했을 때, for문의 각 step에서 계산하는 값(x, sum) 중 이전 값(이전의 for문 step)에 dependent한 부분은 없다. 즉 완벽히 패러럴하게 수행될 수 있는데, 문제는 sum에 관련된 다음의 두가지 경우에서 발생한다.

1. sum이 shared data가 된다. 이 경우 두 스레드는 sum데이터를 메모리 안에서 공유하게 되므로 매 step마다 sum을 메모리에서 fetch하고 store해야되는데 이 경우 sum을 레지스터 안에 두고 계산하는 싱글 스레드의 경우보다 훠얼씬 느려진다. (일반적으로 위의 코드같은 경우라면 계산과정에서 sum을 메모리에 저장하지 않고 레지스터에 저장한다고 함.)

2. sum이 private data가 된다. 이렇게 되면 두 스레드는 각 코어의 레지스터를 활용하게 되므로 memory access에 속도는 문제가 없지만 두 스레드에 의해 각각 계산된 sum값을 마지막에 합쳐야 한다. 물론 계산식을 살펴보면 각각 계산해서 합쳐도 결과는 동일하지만, 프로그래머가 로직을 보고 어느 변수에 대해 리덕션을 해줄지 항상 결정해줘야 한다. 이 과정에서 실수가 발생할 확률이 매우 높다.

쿼드코어에서 아래 코드를 3가지 방법으로 수행하면

 for(int i = 0; i < num_steps; i++)
  sum += i;

다음과 같은 결과가 나온다.

-single (single thread로 계산)
Reached result 542894464 in 0.047 seconds

-shared (sum을 스레드에서 공유.)
Reached result 1259473052 in 0.203 seconds

-reduction (sum을 스레드마다 private하게 가지고, 계산이 끝나면 합침)
Reached result 542894464 in 0.015 seconds

재밌는건 shared로 했을 때, 메모리 엑서스 속도때문에 싱글 스레드보다 오히려 5배정도 느리고 계산결과도 정확하지 않다는 점이다. (아마 shared에서는 변수에 쓸 때 락을 걸지 않는 것 같다.)

반면 reduction에서는 계산 결과도 정확하고 성능도 약 3배정도로 적절하지만 reduction할 변수를 프로그래머가 지정해야 된다는 점에서 상당히 쓰기 불안한 부분이 있다.

결과적으로 openmp가 멀티스레드의 불편함을 줄여주기는 하지만 완전하지는 않은 것 같다.
댓글
댓글쓰기 폼