Parallel Patterns Library(PPL) - parallel_for_each 알고리즘
VC++ 10 Concurrency Runtime 2009. 9. 12. 00:30C++의 STL을 알고 있는 분들은 ‘parallel_for_each’에서
‘parallel_’만 빼면 남는 ‘for_each’는 본적이
있고 사용해본 경험도 있을 것입니다.
parallel_for가 for문을 병렬화 한 알고리즘이라면
parallel_for_each는 STL의
for_each 알고리즘을 병렬화 한 것입니다.
STL 컨테이너에 있는 데이터를 처리할 때 for_each를 사용한 것을 쉽게 parallel_for_each로 바꾸어 아주 손 쉽게 병렬화 할 수 있습니다.
parallel_for_each의 원형
template
< typename _Input_iterator, typename _Function >
_Function
parallel_for_each( _Input_iterator _First, _Input_iterator _Last, _Function _Func );
_First
: 시작 위치
_Last :
마지막 위치
_Func :
병렬 처리에 사용할 함수(함수 객체, 함수, 람다 식)
for_each에 대해서 알고 있는 분들은 앞서 소개한 parallel_for 보다 더 쉽다고 느낄 것입니다. 기존의 for_each가 사용하는 파라미터도 같습니다. 기존에 사용했던 for_each를
parallel_for_each로 바꿀려면 알고리즘 이름만 바꾸어도 됩니다.
초 간단
parallel_for_each 사용 방법
1. 필요한 헤더 파일 포함
#include
<ppl.h>
2.네임 스페이스 선언
using namespace
Concurrency;
3. parallel_for_each에서 사용할 함수 정의
4. parallel_for_each에서 사용할 STL 컨테이너
정의
5. parallel_for_each 사용
parallel_for_each를 사용하는 간단한 예제
#include <iostream>
#include
<algorithm>
#include
<vector>
using namespace std;
#include
<ppl.h>
using namespace Concurrency;
int main()
{
vector<
int > ItemCdList(10);
generate( ItemCdList.begin(), ItemCdList.end(), []() -> int {
int n = rand();
return n; }
);
cout << "for_each" << endl;
for_each( ItemCdList.begin(),
ItemCdList.end(), [] (int n) {
cout
<< "<" << n
<< ">"; } );
cout << endl <<
endl;
cout << "parallel_for_each - 1" << endl;
parallel_for_each(
ItemCdList.begin(), ItemCdList.end(), [] (int
n) {
cout
<< "<" << n
<< ">"; }
);
cout << endl <<
endl;
cout << "parallel_for_each - 2" << endl;
critical_section rt;
parallel_for_each(
ItemCdList.begin(), ItemCdList.end(), [&] (int
n) {
rt.lock();
cout
<< "<" << n
<< ">";
rt.unlock();
}
);
getchar();
return
0;
}
위 예제는 vecter 컨테이너에 램덤으로 10개의
숫자 값을 채운 후 출력하는 것입니다.
for_each와 paralle_for_each 사용 방법이 이름만 다를 뿐 똑 같습니다.
위 예제를 ‘초 간단 parallel_for_each 사용
방법’의 순서에 비추어 보면 아래 그림과 같습니다.
위 예제의 결과입니다.
공유 자원 동기화 문제
parallel_for 때도 잠시 언급했듯이
parallel_for_each는 순서대로 실행하지 않고 병렬로 실행하므로 for_each를
사용한 것과 비교해 보면 출력 순서가 서로 다릅니다.
그리고 특히 문제가 되는 것이 공유 자원을 사용할 때 따로 동기화 시키지 않으면 원하지 않는 결과가 나옵니다.
위와 같은 잘못된 결과는 나올 수도 있고 안 나올 수도 있습니다. 즉 타이밍에 의해서 발생하는
것이기 때문입니다. 이것이 병렬 프로그래밍의 어려움 중의 하나인데 에러가 언제나 발생하면 빨리 발견하여 처리할
수 있는데 공유 자원을 동기화 하지 않았을 때 발생하는 문제는 바로 발생할 수도 있고 때로는 여러 번 실행했을 때 간혹 나올 때도 있어서 버그
찾기에 어려움이 있습니다.
공유 자원의 동기화가 깨어지는 것을 막기 위해서는 동기화 객체를 사용하면 됩니다. 위 예제에서
두 번째 사용한 parallel_for_each는 ‘critical_section’이라는
동기화 객체를 사용하여 공유 자원을 안전하게 보호하고 있어서 올바르게 값을 출력하고 있습니다.
‘critical_section’에 대해서는 다음 기회에 자세하게 설명하겠습니다.
parallel_for_each에 대해서는 이것으로 마무리하고 다음 번에는 parallel_invoke에 대해서 설명하겠습니다.
'VC++ 10 Concurrency Runtime' 카테고리의 다른 글
Parallel Patterns Library(PPL) - parallel_invoke (0) | 2009.10.20 |
---|---|
Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 2 (0) | 2009.09.17 |
Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 1 (1) | 2009.09.02 |
Parallel Patterns Library(PPL) - parallel_for 알고리즘 (5) | 2009.09.01 |
Parallel Patterns Library(PPL) - 병렬 알고리즘 (0) | 2009.08.19 |