Visual C++10을 활용한 병렬 프로그래밍

Post on 18-Jun-2015

1.603 views 20 download

Transcript of Visual C++10을 활용한 병렬 프로그래밍

마이에트 엔터테인먼트 Server Programmer

최흥배

Microsoft Visual C++ MVP

Twitter : @jacking75

Visual Studio 2010 을 활용한 C++ 병렬 프로그래밍

1. Multi-Core 시대2. 어려운 병렬 프로그래밍3. 진화4. Concurrency Runtime5. 병렬 패턴 라이브러리 ( PPL )

목차

Multi-Core 시대

Multi-Core 컴퓨터는 이미 일반화

throughput 컴퓨팅 시대

• 싱글 CPU 의 스피드 향상의 한계에 도달 .

• 멀티 코어 CPU 로 방향을 바꿈 .

• throughput 가 최대 중요 요소가 됨 .

• Intel, AMD 의 CPU 아키텍처는 Multi-Core 를 넘어서 heterogeneous( 헤테로지니아스 ) 로 가고 있음 .

• 2 코어를 융합한 클러스터 .

• 「 Bulldozer Module 」이라고 부른다 .

• 2 개의 스레드를 병렬로 실행할 수 있는 모듈이 Bulldozer의 기본 단위 . 기본은 하나가 아니고 두 개다 !!!

• 4 코어의 Bulldozer CPU 라면 두 개의 Bulldozer Mod-ule 을 탑재 .

• Hyper-Threading 이 아니다 !!!

AMD - Bulldozer 아키텍처

• Intel 의 Hyper-Threading 에서는 CPU 전체의 자원을 명령 단위로 2 개의 스레드에서 공유한다 .

• Bulldozer 에서는 CPU 의 자원 중 정수 연산 파이프는 2 개의 스레드가 각각 전용 파이프를 가진다 .

• 그러나 명령 디코더나 부동 소수점 연산 유닛 등은 2개의 스레드에서 공유한다 .

• 정수 연산에서는 스레드간의 경합이 없기 때문에 throughput 가 높다 ,

Hyper-Threading 과의 차이

Intel - Larrabee 아키텍처

• 현재 Intel 은 「 Larrabee( 라라비 ) 」를 그래픽스 제품으로서 투입하는 것을 단념 .

• 그러나 Intel 이 CPU 에 통합하기 위한 데이터 병렬 중시형 프로세서 코어의 아키텍처를 긴급하게 필요로 하고 있는 점은 변화지 않음 .

• Larrabee 의 목적은 어떻게 하면 유연하고 고효율이면서 프로그램 하기 쉬운 아키텍처로 할 수 있을지를 추구하는 것 .

• Intel 의 간부들은 Larrabee 와 같은 범용 데이터 병렬 코어를 CPU 로 통합하는 것을 전망 .

• 효율성으로 말하면 대형 슈퍼 스칼라 코어와 소형의 데이터 병렬 특화형 코어의 편성의 헤테로지니아스 ( 이종 혼합 ) 구성이 바람직하다 .

• 왜냐하면 지금부터 퍼포먼스를 늘리고 싶은 것은 데이터 병렬로 부동 소수점 연산 중심의 작업 부담량이기 때문 .

• Amdahl 의 법칙은 여전히 살아 있기 때문에 Intel 은 대형 슈퍼 스칼라 코어를 버리고 가는 것도 할 수 없다 . 필연적으로 헤테로지니아스가 된다 .

어려운 병렬 프로그래밍

병렬 프로그래밍 ? Multi-Core? 그거 먹는 건가요 ? 우걱우걱

race condition, dead lock

void SetReUseSocket(){ ……… if( flase == m_bUsed ) { LOG(“SetReUseSocket() | Failed”); return; }

LOG(“SetReUseSocket()”);

m_bUsed = true; ………}

진화

2002 년 2010 년

OS – 2001 년과 2009 년

Windows XP Windows 7

Visual Studio – 2002 년과 2010 년

Visual Studio.NET( 2002)

Visual Studio 2010

2008 년 10 월 Microsoft 의 최고 연구 전략 책임자를 맡은 Craig Mundie 씨

- Win32 는 비동기 병렬 컴퓨팅에는 적합하지 않는 것을 인정 .

- Windows 7 및 Windows Server 2008 R2 에서 문제 해결을 위해 첫발을 내딪음 .

- Windows 는 지금이라도 2,3 의 코어 머신을 처리할 수 있지만 8, 16 또는 32 이상의 코어 머신을 사용하도록 설계되어 있지 않다 .

- Windows 를 보다 뛰어난 병렬 / 비동기 프로세싱 플랫폼화 하기 위한 최초의 씨앗은 2009 년부터 뿌려지기 시작 .

Core 2

Thread3

Non-running threads

Core 1

Thread4

Thread5

Thread1

Thread2

Thread6

Core 2Core 1

UserThrea

d2

KernelThrea

d2

UserThrea

d1

KernelThrea

d1

UserThrea

d3

KernelThrea

d3

UserThrea

d4

KernelThrea

d4

UserThrea

d5

KernelThrea

d5

UserThrea

d6

KernelThrea

d6

Thread Scheduling

UMS - Cooperative Schedul-ing

그림 출처 : PDC 09

• 대기 중인 스레드의 커널 모드에서의 Block 이 풀리면

• 대응하는 유저 모드 스레드는 Completion List 에 등록되어

• 코어에서 실행 중인 스레드가 종료하는 것을 기다린 후 다시 실행한다 .

UMS - Completion List

Group

NUMA NodeSocket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

Socket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

NUMA NodeSocket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

Socket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

Group

NUMA NodeSocket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

Socket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

NUMA NodeSocket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

Socket

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

CoreLP

LP

LP

LP

NUMA

그림 출처 : PDC 09

Parallel Pattern Library

Resource Manager

Task Scheduler

ThreadsOperat-ing Sys-tem

Native Concurrency Runtime

Data

Str

uctu

res

AsynchronousAgentsLibrary

UMS Threads

Native LibrariesIn

tel

® Open

MP

Inte

l ® T

BB

ToolsVisual Stu-dio 2010

ParallelDebug-

gerProfiler Concur-rency

Analysis

Intel Paral-lel Studio

Parallel Com-poserParallel

Inspec-tor

Parallel Amplifier

Concurrency Runtime

그림 출처 : PDC 09

Concurrency Runtime(ConcRT)

Resource Manager

Task Scheduler

OS

Parallel Patterns Library

Asynchronus Agents Library

Synchronization Data Struc-tures

• 작업을 작고 세밀하게 처리할 수 있도록 범용적인 컨테이너와 알고리즘 제공

• Imperative parallelism – parallel_for, parallel_for_each 등

• Task parallelisn – task_group, structured_task_group

Parallel Patterns Library(PPL)

• Actor 베이스 모델 및 메시지 전달을 통해서 작고 세밀한 data flow 와 task pipeniling 을 제공

• AAL 은 다른 컴포넌트의 데이터를 기다리면서 작업을 처리 할 수 있다 .

• AAL 은 복수의 엔티티가 서로간에 비동기로 통신을 할 때 사용한다 .

Asynchronous Agents Library(AAL)

class GameAI : public agent {..... void run() { // Send the request. ...... send(_target, wstring(L"request"));

// Read the response. int response = receive(_source); }

private: ISource<int>& _source; ITarget<wstring>& _target;};

class GameLogic : public agent {..... void run() { // Send the request. ...... send(_target, wstring(L"request"));

// Read the response. int response = receive(_source); }

private: ISource<int>& _source; ITarget<wstring>& _tar-get;};

• 여러 스레드로부터 공유 데이터 접근을 동기화 할 수 있는 몇 개의 데이터 구조를 제공 .

• 동기 오브젝트는 크리티컬 섹션과 같이 다른 스레드로부터 공유 데이터를 사용할 수 있을 때까지 기다린다 .

• critical_section, reader_writer_lock, event

Synchronization Data Structures

• 실행 시에 task 의 스케쥴링 및 조정을 한다 .

• cooperative 스케쥴링과 work-stealing 알고리즘을 사용하여 최대한 효율이 좋게 리소스를 처리하도록 한다 .

• Concurrency Runtime 은 기본적인 스케쥴러를 제공하므로 직접 관리할 필요는 없다 .• 다만 우리가 만든 애플리케이션에 최적화 시켜 더 높은 성능을 얻고 싶을 때는 스케줄러의 정책을 변경하거나 특별한 task, 특별한 스케줄러와 제휴할 수 있다 .

Task Scheduler

• Processors 나 메모리 등의 컴퓨팅 리소스를 관리하는 것이 목적 .

• 실행 시에 작업 부하에 변경이 일어나면 가장 효율이 좋게 처리할 수 있도록 리소스를 할당 .

• 컴퓨팅 리소스를 추상화하여 Task Scheduler 와 주로 대화 .

• 더 높은 성능을 얻기 위해서 Resource Manager 를 세밀하게 조정할 수 있다 .• 다른 병렬 라이브러리의 병행 런타임과 컴퓨팅 리소스 관리를 통합 할 수 있다 .

Resource Manager

CPU0 CPU1 … CPUN

BigBig

Big

Big

SmallSmallSmall Small

Dynamic Scheduling

CPU0 CPU1 … CPUN

Big

Big

Big

SmallSmall Small

Small

Big

Static Scheduling

ConcRT 의 Cooperative

Demo

코어 증가와 Resource Management

• 4 개의 Core 를 가진 ConcRT 를 사용한 프로세스가 두개 실행 중이라면 , 하나의 ConcRT 는 Core 0, Core 1 에서 , 두 번째 ConcRT 는 Core 2, Core 3 에서 실행

#include "stdafx.h"#include <ppl.h>using namespace Concurrency;

int main(){ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

parallel_invoke( [] { }, [] { } ); return 0;}

ConRT Memory leak?

• 위 코드는 디버그 모드에서 메모리 릭을 경고 .

• 이유는 Task Scheduler 와 Resource Manage 가 파괴되기 전에 프로그램이 종료 되기 때문 .

int main(){ HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); CurrentScheduler::Create( SchedulerPolicy() ); CurrentScheduler::RegisterShutdownEvent( hEvent );

_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

parallel_invoke( [] {}, [] {} );

CurrentScheduler::Detach(); WaitForSingleObject( hEvent, INFINITE ); CloseHandle( hEvent ); Sleep(500);

return 0;}

병렬 패턴 라이브러리 ( PPL )

PPL 의 세 가지 features

• Task Parallelism

• Parallel algorithms

• Parallel containers and objects

3D 게임을 실행하면…Font 리소스 로딩Texture 리소스 로딩3D 모델링 리소스 로딩 등등…

Task Parallelism

− 실제적인 task 의 실행은 task_group 에서 한다 .

− unstructured_task_group(task_group) 와 structured_task_group 로 나누어진다 .

− task_group : 스레드 세이프 structured_task_group : 스레드 세이프 하지 않음 .

Thread Atask_group1.run( task2)

Thread Btask_group1.run( task3)

task_group1.run( task1)

Thread Astructured_task_group1.run( task2)

structured_task_group1.run( task1)

Main Thread

Main Thread

초 간단 !!! task 사용 방법1. ppl.h 파일을 포함합니다 .

#include <ppl.h>

2. Concurrency Runtime 의 네임 스페이를 선언합니다 . using namespace Concurrency;

3. 태스크 그룹을 정의합니다 .structured_task_group structured_tasks;

4. 태스크를 정의합니다 . auto structured_task1 = make_task([&] { Plus(arraynum1, true); } );

5. 태스크를 태스크 그룹에 추가한 후 실행합니다 .  structured_tasks.run( structured_task1 );

6. 태스크 그룹에 있는 태스크가 완료될 때까지 기다립니다 . structured_tasks.wait();

ConcRT 의 Task

Demo

for( i = 0; i < 1000000; ++i ){ ………… …………}

Parallel Algorithms

− 데이터 컬렉션을 대상으로 쉽게 병렬 작업을 할 수 있게 해주는 알고리즘들 .

− STL 에서 제공하는 알고리즘과 비슷한 모양과 사용법 .

− paeallel_for, parallel_for_each, parallel_invoke 가 구현되어 있음 .

parallel_accumulate, parallel_partial_sum 는 다음 버전 ?

parallel_for− for 문을 병렬화 .

− for 문과 사용 방법이 흡사하여 쉽게 변환 .

− step 값을 지정하는 버전과 지정하지 않는 버전 두 개가 있음 (지정하지 않으면 1).

− index 조사는 ‘<‘만 지원 .

초 간단 !!! parallel_for 사용 법1. ppl.h 파일을 포함합니다 .

#include <ppl.h>

2. Concurrency Runtime 의 네임 스페이를 선언합니다 . using namespace Concurrency;

3. parallel_for 에서 호출할 함수 정의

4. parallel_for 에서 사용할 data set 정의 .

5. parallel_for 사용 .

parallel_for_each

− STL 의 for_each 알고리즘을 병렬화 .

− for_each 와 사용 방법이 같음 .

초 간단 !!! parallel_for_each 사용 법1. ppl.h 파일을 포함합니다 .

#include <ppl.h>

2. Concurrency Runtime 의 네임 스페이를 선언합니다 . using namespace Concurrency;

3. parallel_for_each 에서 호출할 함수 정의

4. parallel_for_each 에서 사용할 data set 정의 .

5. parallel_for_each 사용 .

parallel_invoke

− 병렬로 일련의 태스크 실행 .

− 동시 실행할 복수의 독립된 태스크를 실행할 때 좋음 .

− task_group 과 비슷하나 사용방법은 더 쉬움그러나 최대 10 개의 태스크만 병렬 작업이 가능하다 .

초 간단 !!! parallel_invoke 사용 법1. ppl.h 파일을 포함합니다 .

#include <ppl.h>

2. Concurrency Runtime 의 네임 스페이를 선언합니다 . using namespace Concurrency;

3. 태스크 정의

4. parallel_invoke 사용 .

parallel objects - combinable

− 스레드 세이프한 오브젝트 .

− 계산 실행 후 최종 결과에 그 계산 결과를 통합하는 재 사용 가능한 로컬 스트리지 제공 .

− 복수의 스레드 또는 태스크 간에 공유 리소스가 있는 경우 편리 .

− lock-free thread-local sub-computations during parallel al-gorithms

− combinable 클래스에 사용할 데이터는 기본 생성자와 복사 생성자를 가지고 있어야 한다 .

− Win32 API 의 thread local storage 와 비슷 .

− combine, combinable_each 제공

concurrent containers

− 병렬 환경에서 스레드 세이프하게 데이터를 저장 .

− concurrent_queue, concurrent_vector,.

− concurrent_hash_map 은 다음 버전 ?

concurrent_vector• 병렬 프로그래밍에 접합한 STL vector 타입의 컨테이너 .

• 전체적인 인터페이스는 vector 와 비슷하나 제한이 있슴 .

• 기존 요소의 값을 변경할 때는 스레드 세이프하지 않음 . 기존 요소의 값을 변경할 때는 동기화 객체를 사용하여 lock 을 걸어야 합니다 .

• concurrent_vector 사용 방법- concurrent_vector 를 사용하기 위해서 먼저 헤더 파일을 포함해야 합니다 .- concurrent_vector 의 헤더 파일은 “ concurrent_vector.h” 입니다 .- STL 의 vector 사용 방법과 거의 같음 .

기능 vctor Concurrent_vector

추가 스레드에 안전하지 않음 스레드에 안전

요소에 접근 스레드에 안전하지 않음 스레드에 안전

반복자 접근 및 순회 스레드에 안전하지 않음 스레드에 안전push_back 가능 가능insert 가능 불가능clear 모두 삭제 모두 삭제erase 가능 불가능pop_back 가능 불가능

배열식 접근 예 . &v[0]+2

가능 불가능

grow_by, grow_to_at_least (vector의 resize 와 비슷 ) 는 스레드에 안전하지 않음

추가 또는 resize 때 기존 인덱스나 반복자의 위치가 바뀌지 않음

bool 형은 정의 되지 않았음

concurrent_deque• 병렬 프로그래밍에 접합한 STL deque 타입의 컨테이너 .

• enqueue 와 dequeue 조작이 스레드 세이프 하다 .

• 반복자를 지원하지만 스레드 세이프 하지 않다 .

• front 와 pop 함수를 지원하지 않음 . 대신에 try_pop 함수를 대신해서 사용 .

• back 함수를 지원하지 않는다 . 그러므로 마지막 요소를 참조하는 것은 불가능하다 .

• size 메소드 대신 unsafe_size 함수를 지원한다 . unsafe_size 는 이름 그대로 스레드 세이프 하지 않다 .

• 사용 방법 - “concurrent_queue.h” 파일을 include 한다 . - 사용 방법은 STL 의 deque 와 비슷 .

스레드 세이프한 concurrent_queue 의 함수

- concurrent_queue 에 enqueue 또는 dequeue 하는 모든 조작에 대해서는 스레드 세이프합니다 .- empty- push- get_allocator- try_pop- empty 는 스레드 세이프하지만 empty 호출 후 반환되기 전에 다른 스레드에 의해서 queue 가 작아지던가 커지는 경우 이 동작들이 끝난 후에 empty 의 결과가 반환됩니다 .

스레드 세이프 하지 않은 concurrent_queue 의 함수

- clear- unsafe_end- unsafe_begin- unsafe_size

Intel 의 TBB 를 배운 후 ConcRt 를 보면……

ConcRt 를 배운 후 TBB 를 보면……

참고

AMD 가 차기 아키텍쳐 「 Bulldozer 」와「 Bobcat 」의 개요를 공표원문 : http://pc.watch.impress.co.jp/docs/column/kaigai/20091112_328392.html번역 :http://jacking.tistory.com/487http://jacking.tistory.com/488http://jacking.tistory.com/489

2011 년에 등장하는 AMD 의 8 코어 데스크탑 CPU 「 Zambezi 」원문http://pc.watch.impress.co.jp/docs/column/kaigai/20091126_331235.html번역http://jacking.tistory.com/514http://jacking.tistory.com/515http://jacking.tistory.com/516

Core i5/i7원문http://www.atmarkit.co.jp/fwin2k/words/011corei5/corei5.html번역http://jacking.tistory.com/510http://jacking.tistory.com/511

계획이 바뀐 Larrabee 무엇이 문제였는가 ?http://jacking.tistory.com/517http://jacking.tistory.com/518

마이크로소프트 Windows 7 에서도 병렬처리 향상을 목표로 http://jacking.tistory.com/355

[PDC09] Developing Applications for Scale-Up Servers Run-ning Windows Server 2008 R2http://microsoftpdc.com/Sessions/SVR18

[PDC09] Lighting up Windows Server 2008 R2 Using the Con-cRT on UMShttp://microsoftpdc.com/Sessions/SVR10

양보할 줄 아는 Concurrency Runtime 의 eventhttp://vsts2010.tistory.com/109

Cross Process Resource Management - do we need it now?http://blogs.msdn.com/nativeconcurrency/archive/2010/04/07/cross-process-resource-management-do-we-need-it-now.aspx

Concurrency::task_group leaks memoryhttp://social.msdn.microsoft.com/Forums/en/parallelcppnative/thread/15799a79-cca0-4c51-85e3-64ea1e26981d

MSDN – Concurrency Runtimehttp://msdn.microsoft.com/en-us/library/dd504870(VS.100).aspx

VSTS 2010 스터디 블로그http://vsts2010.net

Parallel Programming in Native Codehttp://blogs.msdn.com/nativeconcurrency/default.aspx

본인 블로그http://jacking.tistory.com/