원래 저번 주에 글을 올릴 예정이었으나 근래에 제 몸 상태와 집 PC 상태가 메롱이 되어버려 한 주 늦게 글을 올립니다(혹시 기다리고 계시는 분이 있었는지 모르겠네요 ^^;;; )
for 문의 병렬화
이번에는 PPL의 세 개의 알고리즘 중 parallel_for 알고리즘에 대해서 이야기 하겠습니다.
앞 글에서 간단하게 설명했듯이 parallel_for는 그 이름을 보면 유추 할 수 있듯이 for 문을 병렬화 한 알고리즘입니다.
아주 많은 횟수로 반복 작업을 해야할 때 하나의 스레드로 처리하는 것보다는 여러 스레드로 동시에 처리하면 훨씬 빨라지는 것은 당연하겠죠? 바로 이 때 사용하면 좋습니다.
하지만 parallel_for 알고리즘은 아무 곳에나 사용할 수는 없습니다. 루프의 반복 계산 사이에 리소스를 공유하지는 않으면서 루프의 본체가 있는 경우 사용하면 편리합니다.
( 앞의 계산 결과를 다음 계산에서 사용해야 된다면 병렬로 실행하기 힘듭니다 )
parallel-for의 원형
두 개의 오버로드 버전이 있습니다.
template < typename _Index_type, typename _Function >
_Function parallel_for( _Index_type _First, _Index_type _Last, _Function _Func );
_Index_type _First : 시작 위치
_Index_type _Last : 마지막 위치
_Function _Func : 병렬 처리로 사용할 함수
template < typename _Index_type, typename _Function >
_Function parallel_for( _Index_type _First, _Index_type _Last, _Index_type _Step, _Function _Func );
_Index_type _First : 시작 위치
_Index_type _Last : 마지막 위치
_Index_type _Step : 증분 값
_Function _Func : 병렬 처리로 사용할 함수
파라미터 값을 보면 for에서 사용하는 것과 비슷하다는 것을 알 수 있을겁니다. 차이점은 첫 번째 버전의 경우 증분 값으로 1이 자동으로 사용된다는 것과 마지막 파리미터로 병렬 처리에 사용할 함수를 사용한다는 것입니다.
for와 비슷하므로 for를 사용하는 대 부분을 prarallel_for로 변경할 수 있습니다. 다만 parallel_for 알고리즘에서는 반복 변수의 현재 값이 _Last 보다 작으면 중단합니다 ( 보통 for 문과 다르게 ‘<’ 조건만 사용합니다 ).
또 _Index_type 입력 파라미터는 정수형이어야만 합니다.
parallel_for 파라미터가 1보다 작은 경우 invalid_argument_Step 예외를 던집니다.
초 간단 parallel_for 사용 방법
1. 필요한 헤더 파일 포함
#include <ppl.h>
2. 네임 스페이스 선언
using namespace Concurrency;
3. parallel_for에서 호출할 작업 함수 정의
4. parallel_for에서 사용할 data set 정의
5. parallel_for 사용
#include <ppl.h>
#include <iostream>
using namespace Concurrency;
using namespace std;
int main()
{
int CallNum = 0;
int Numbers[50] = { 0, };
parallel_for( 0, 50-1, [&]( int n ) {
++CallNum;
Numbers[n] += CallNum;
}
);
for( int i = 0; i < 50; ++i )
{
cout << i << " : " << Numbers[i] << endl;
}
getchar();
return 0;
}
위 예제는 Numbers라는 int 형 배열의 각 요소에 CallNum 이라는 변수를 더하는 것입니다. 간단하고 확실하게 parallel_for 사용 방법을 보이기 위해 허접한 예제를 만들게 되었음을 양해 바랍니다.^^;;; ( 다음에 기회가 되면 좀 더 멋지고 실용적인 예제를 보여드리도록 하겠습니다 )
위 예제를 '초 간단 parallel_for 사용 방법'의 순서에 비추어보면 아래 그림과 같습니다.
예제를 실행하면 아래와 같은 결과가 나옵니다.
(길어서 일부만 캡쳐 했습니다)
실행 결과를 보면 Numbers 배열의 각 요소의 값이 순서대로 증가되지 않았다라는 것을 알 수 있습니다. 만약 보통의 for 문이라면 Numbers[0]은 1, Numbers[1]은 2 라는 값으로 됩니다. 그러나 parallel_for는 병렬적으로 실행되므로 순서가 지켜지지 않습니다. 또 CallNum 라는 변수는 parallel_for의 모든 스레드에서 접근하는 공유 변수이므로 동기화 되지 않았다라는 것도 유의해야 합니다.
Parallel_for를 사용할 때 순서대로 실행하지 않고, 공유 변수는 동기화 되지 않음을 잊지마시기를 바랍니다.
이것으로 (너무?)간단하게 parallel_for에 대해서 알아 보았습니다. 다음에는 parallel_for_each에 대해서 설명하겠습니다.
수정
1. 덧글의 ivyfore님이 알려주신대로
parallel_for( 0, 50-1, [&]( int n )가 아닌
parallel_for( 0, 50, [&]( int n ) 가 되어야 합니다.
'VC++ 10 Concurrency Runtime' 카테고리의 다른 글
Parallel Patterns Library(PPL) - parallel_for_each 알고리즘 (0) | 2009.09.12 |
---|---|
Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 1 (1) | 2009.09.02 |
Parallel Patterns Library(PPL) - 병렬 알고리즘 (0) | 2009.08.19 |
Parallel Patterns Library(PPL) - Task (2) | 2009.08.18 |
양보할 줄 아는 Concurrency Runtime의 event (1) | 2009.08.07 |