최근 포토로그


Parallel Programming, OpenMP 그리고 Win32 - 1 복잡한컴퓨터이야기

기술적인 이야기를 풀어 나가는 글들은 앞으로 높임말을 사용해 볼까 합니다. 그렇지 않아도 어려운 내용들을 이야기 하면서, 단정적인 어투를 사용하니까 글이 더욱 더 딱딱해져서 읽기가 힘든 것 같더라고요.

OpenMP는 다양한 Platform에서 비전문가가 병렬 수행이 가능한 application을 개발할 수 있도록 해주기 위한 compiler directive, library function, environment variable의 집합입니다.
OpenMP는 사실 Fortran 언어를 위해서 처음 개발되었는데, 나중에 C/C++ 개발자들을 위해서 포팅 되었습니다. 제가 Fortran 언어의 전문가는 아니지만, 오래 전 기억을 더듬어 보면 Fortran 언어 차원에서 Platform이 제공하는 Thread관련 기능을 제어할 수 있는 기능은 없었던 것 같습니다.(혹시 이 글을 보시는 Fortran 전문가가 계시다면 확인 부탁드릴께요.)
Fortran 언어가 수학, 공학에 특화된 언어라는 사실은 Fortran 언어를 공부해보시지 않은 분들도 아실 텐데, 만일 다수의 CPU 혹은 다수의 Core를 가진 CPU를 가진 machine에서 Fortran 언어로 개발된 binary를 수행할 경우에, CPU의 성능을 100% 활용하기란 쉽지 않겠죠. 이 경우 다수의 CPU 혹은 다수의 Core사이에 Load Balancing을 OS 혹은 CPU 차원에서 해주어야 하는데, 알고리즘을 정확히 모른 상태에서 작업을 완벽히 배분한다는 것은 거의 불가능하기 때문입니다. 이런 이유로 인해 OpenMP가 Fortran 언어에 가장 먼저 적용된 것이 아닐까 생각해 봅니다.
OpenMP를 전혀 모르는 분들도 있을 테니 약간 역사를 짚어보는 것도 좋을 것 같습니다. OpenMP와 유사한 시도들은 90년대 초반에 이루어졌다고 하고요, 실제 OpenMP에 대한 Spec.이 만들어지기 시작한 시점은 1997년 봄부터 입니다.

openMPtimeline 

(위 그림에서 Fortran 1.0 혹은 C/C++ 1.0 이라고 쓰여진 것은 Fortran 언어 1.0이 아니라 Fortran용 OpenMP version 1.0 이라고 보셔야 합니다.)

가장 최근의 Spec은 위 그림에서 보실 수 있는 바와 같이 OpenMP 3.0인데요, Visual Studio 2010의 경우에는 OpenMP 2.0 까지 만을 지원하고 있습니다.
Visual Studio 2010 에서 간단하게 Hello OpenMP!를 작성하는 것으로 시작해 볼까 합니다. C/C++ Console Application Project를 생성하시고 다음과 같이 Project 설정을 변경합니다.

image

이제 준비는 끝났습니다. Hello, OpenMP! 의 source는 다음과 같습니다.

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
#pragma omp parallel
_tprintf(_T("Hello, OpenMP!\n"));

return 0;
}

코드를 살펴보면 “#pragma omp parallel”이라고 추가한 게 전부인 것 같군요. 그런데 수행 결과는 약간 놀랍습니다.


image


loop를 통한 iteration이 없었음에도 “Hello, OpenMP!”가 4번이나 출력되었네요. 약간 신기합니다. 눈치가 빠르신 분은 “아! #pragma 저 눔에 뭔가 내부적으로 이상한 짓을 하는구나”라고 생각하셨을 겁니다. 좀 더 도가 통하신 분이라면 “아! #pragma omp가 다수의 thread를 생성하여 각각이 그 이하의 구문을 수행하는 구나.”까지 예상하실 수 있을지도 모릅니다.


좀 더 자세히 살펴볼까요? Visual Studio 2010의 Threads 창을 이용하면 현재 수행 중인 Thread 들이 무엇을 하고 있는지 확인할 수가 있죠.


image


오호라 정말 Thread가 4개가 생성되긴 했군요. 그런데 왜 하필 10개도 아니고 2개도 아니고 4개 일까요? 다음은 이 프로그램을 수행한 machine의 작업 관리자의 모습입니다.


image



네 그렇습니다. 제 machine은 Quad Core CPU입니다. 그래서 아마도 Thread가 4개가 생성되었나 봅니다. Dual Core CPU 2장이나, CPU 4장이 설치되어 있는 machine도 같은 형태로 나타나겠지요.
그런데 사실 위 프로그램은 쓸모가 없죠. CPU의 type 혹은 CPU의 core 갯수에 따라서 출력 결과가 달라질 테니까요. 또한 CPU의 core 갯수만큼 Thread를 생성한다는 것도 Visual Studio 2010에서 지원하는 OpenMP의 세부 구현 특성이지 모든 OpenMP가 이처럼 동작한다는 보장은 없어요.
만일 여러분이 WIN32 API를 이용해서 이와 같은 프로그램, 즉 “CPU 갯수와 core의 갯수를 고려하여 Thread를 생성한 후, Hello, OpenMP!를 출력하는” 프로그램을 작성한다면 어떻게 될까요? 여러분을 대신해서 제가 한번 작성해 보겠습니다.

// openmptest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <process.h>

int GetNumberOfCores()
{
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pProcessorInformations = nullptr;
DWORD length = 0;

BOOL result = GetLogicalProcessorInformation(pProcessorInformations, &length);
if (!result)
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
pProcessorInformations = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)new BYTE[length];
}
}

result = GetLogicalProcessorInformation(pProcessorInformations, &length);
if (!result)
{
// error
return -1;
}

int numOfCores = 0;
for (int i = 0 ; i < length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) ; i++)
{
if (pProcessorInformations[i].Relationship == RelationProcessorCore)
numOfCores++;
}

delete [] pProcessorInformations;

return numOfCores;
}

DWORD WINAPI ThreadFunc(LPVOID)
{
_tprintf(_T("Hello, OpenMP!\n"));
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
//#pragma omp parallel
//_tprintf(_T("Hello, OpenMP!\n"));
int numOfCores = GetNumberOfCores();

HANDLE *pThreads = new HANDLE[numOfCores - 1];

for (int i = 0 ; i < numOfCores - 1 ; i++)
{
pThreads[i] = (HANDLE)_beginthreadex(nullptr, 0, (unsigned int (__stdcall *)(void *))ThreadFunc, nullptr, 0, nullptr);
}

ThreadFunc(nullptr);

WaitForMultipleObjects(numOfCores - 1, pThreads, TRUE, INFINITE);

for (int i = 0 ; i < numOfCores - 1 ; i++)
{
CloseHandle(pThreads[i]);
}

delete [] pThreads;

return 0;
}

만만하지는 않지만 WIN32에 익숙하신 분이라면 이 정도는 하실 수 있겠지요. 그런데 위 코드를 만들 수 있으려면 상당히 많은 부분을 알고 있어야만 합니다.
일단 CPU의 갯수나 Core의 갯수를 얻어내는 방법을 알아야 하고, Thread를 생성하는 방법, Thread Function의 signature, Thread Function의 종료를 대기하는 방법, 더 깊게는 Visual C/C++의 runtime의 특성, TLS 등등…
제가 첨에 그랬잖아요. “OpenMP는 다양한 Platform에서 비전문가가 병렬 수행이 가능한 application을 개발할 수 있도록 해주기 위한 compiler directive, library function, environment variable의 집합” 이라고요.
오늘은 여기까지만…

Parallel Programming, OpenMP 그리고 Win32 - 1

Parallel Programming, OpenMP 그리고 Win32 - 2

Parallel Programming, OpenMP 그리고 Win32 - 3

Parallel Programming, OpenMP 그리고 Win32 - 4

Parallel Programming, OpenMP 그리고 Win32 - 5

Parallel Programming, OpenMP 그리고 Win32 - 6


핑백

  • concurrency &amp; pallelel OpenMP | sol2man2 2011-10-14 10:07:21 #

    ... ks-grand-central-%EA%B7%B8%EB%A6%AC%EA%B3%A0-opencl/ http://trip2ee.tistory.com/tag/IT http://himskim.egloos.com/3261640 http://blog.windage.co.kr/tag/OpenMP http://sunyzero.egloos.com/4283977 OpenMP/Jav ... more

  • # : 병렬 프로그래밍 2013-04-27 23:09:45 #

    ... PPL, OpenMP, TBB 속도 비교VS 2010에 TBB 적용하기병렬처리 강의 OpenMPhttp://himskim.egloos.com/3261640http://trip2ee.tistory.com/67http://cafe.daum.net/betterspeed/91vu/2 ... more

덧글

  • 2011/10/24 17:54 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 김명신 2011/11/01 23:17 # 답글

    @Neodreamer 완전 문제 없습니다. 팍팍! 가져다 팍팍! 고쳐 쓰세요.
  • 장발장 2012/09/25 09:09 # 삭제 답글

    그림이 모두 배꼽으로 나와요 !!
  • 김명신 2012/10/23 16:54 # 답글

    @장발장 이상하네요.. 저는 잘 나오는것 같긴한데 말이죠. 다른 분들도 배꼽으로 보이시나요?
  • 열혈남히이로 2013/09/02 10:59 # 삭제 답글

    최근 분활 다운로드를 이용한 업데이트 프로그램을 만드는데 많은 도움이 되었습니다 감사합니다 :)
  • sosal 2014/01/29 02:47 # 삭제 답글

    좋은 포스트라 트랙백 남깁니다.
  • 2014/10/13 19:58 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 김명신 2014/10/17 16:21 #

    네~
  • 송성우 2015/12/22 17:55 # 삭제 답글

    Open MP 자료 찾다가 들어온 블로그인데 페이스북에 김명신님이었군요~~^^

    좋은 자료 감사합니다.
  • rainblue 2016/10/05 13:17 # 삭제 답글

    회사에 OpenMP 관련 소개 세미나 좀 하려고 합니다.
    만드신 자료가 너무 훌륭하여(^^) 좀 사용하고 싶은데요..
    괜찮습니까~~?
댓글 입력 영역


facebook 프로필 위젯

트위터 위젯