-
Notifications
You must be signed in to change notification settings - Fork 10
Chapter 08, Designing concurrent code
danny song edited this page Nov 13, 2015
·
17 revisions
- 이전 장에서는 C++11으로 동시성 코드를 구현하는 것에 집중했고 특히 6, 7장에서는 다수의 쓰레드에서 동시 접근 안전한
기본적인 데이타 구조 디자인을 살펴봤다. 이제 좀더 넓 문맥에서 동시성 디자인을 하는 방법을 알아보자.
동시성 코드는 다른 프로그래밍 처럼 디자인에 대해서 주의 깊은 관심이 필요하지만, 순차적 코드보다 더 많은 요소를 생각해
야 한다.
예들들어, 데이타 공유 그리고 다수 쓰레드에서 데이타 접근시 데이타 싱크로나이즈, 쓰레드간 싱크로나이즈 등등
이장에서는 다음을 알아본다.
- 얼마나 많은 쓰레드를 사용하는지에 대한 high level관점(그리고 근본적인)에서의 고려
- 어떤 코드가 어떤 쓰레드에서 실행되는지
- 동시성 다지안이 어떻게 코드 명확화에 영향을 끼치는지
- 최적의 성능을 위해 공유 데이타를 어떻게 구조화 하는지 low level관점에서의 고려
- 집을 짓는 다고 생각해보자
- 무엇을 해야 할까?
- 집 터 기초를 다져야 하고 벽을 쌓아야 하며 배관을 설치도 하고 선들도 연결하고 등등...
- 방법
- 나 혼자 배워서 다 한다.
- 시간도 오래 걸리고 이것 저것 할게 많아 문맥 전환이 빈번하다!
- 사람을 고용한다.
- 능숙하진 않지만 모든 기술을 조금씩 알고 있는 사람들 고용 - 여전히 문맥 전환은 존재하지만 혼자하는거보단 빠르다.
- 각 분야의 전문가를 고용한다.
- 각 분야의 전문가가 모여 작업을 하기 때문에 집중도가 높아졌고 문맥 전환 비용이 낮다.
그래서 효율 및 속도는 전체적으로 이전보다 높아졌다. 하지만 각 작업이 특정 전문가에만
의존하기때문에 특정 작업이 없을 경우 그 전문가는 할수 있는게 없다.(go to idle)
- 아마도 특정 분야에 따라 다른 수의 전문가를 고용할 수 있다. 예를들어, 집을 짓는데 전기기사보단 벽돌공이 더 많이 필요하다. 만약 한번에 많은 수의 집을 짓는다면 쉬고 있는 배관공에게 더 많은 일을 줄 수 있다. 만약 할 일이 없는 전문가에게 보수를 지불할 필요가 없다면 같은 숫자의 일할 수 있는 인력으로 더 큰 팀을 꾸릴 수 있다.
- 결국엔 쓰레드를 다루는것도 같은 이치다!
- 얼마나 많은 쓰레드를 써야하고, 어떤 작업을 해야 하고, generalist써야 할지 specialist를 써야 할지..
- 이런 것을 생각하면서 동시성 프로그램 디자인을 디자인해야 하며 디자인에 따라 성능 뿐만아니라 코드 명료성에 지대한 영향을 끼친다.
- 무엇을 해야 할까?
- std::for_each로 간단한 병렬처리를 알아보자.
- 처리 쓰레드에게 각 앨리먼트 연산을 맡길 수 있다. 최상의 성능을 위해 데이타 구조체를 어떻게 나누는가는 그 구조체 자체의 detail에 의존적이다.
- 가장 쉽게는 첫번째 N개 앨리먼트를 첫번재 쓰레드에, 다음 N개를 두번째 이런식으로 처리 책임이 각각 쓰레드에서 맡겨지고
쓰레드 사이에 communcation없이 독립적으로 수행한다.
- 이런 접근법은 Message Passing Interface ( MPI ), OpenMP와 비슷하다.
- 작업이 작은 작업 단위로 나눠지고 각 worker 쓰레드에 assign된다. 결과는 최종 Reduction단계를 거쳐 완성된다.
- secion 2.4에서 accumulate 예제의 접근법이며 for_each는 reduction 단계를 필요없다.
- 작업이 작은 작업 단위로 나눠지고 각 worker 쓰레드에 assign된다. 결과는 최종 Reduction단계를 거쳐 완성된다.
- 이런 접근법은 Message Passing Interface ( MPI ), OpenMP와 비슷하다.
- reduction 단계는 중요하다. listing 2.8같은 초보적인 구현은 reduction 단계를 마지막에 수행할 것이다. 그러나 이 단계 조차도 병렬화될 수 있다. 예들들어, 사실 accumulate 자체가 reduction 연산이여서, 쓰레드의 수가 하나의 쓰레드에서 처리 하는 최소 아이템 수보다 크면 재귀 호출로 구현할 수 있다.
- 그리고 매번 새로운 쓰레드를 생성하는것 대신 각 쓰레드가 나눠진 작업을 완료할 때마다 worker 쓰레드가 reduction 작업을 수행할 수도 있다.
- 하지만 이런 디자인도 데이타의 성격에 따라 적용될 수도 안될 수도 있음을 유의하자. 즉 데이타 그리고 작업의 성격에따라
다자인 되어야 한다.
- 예를 들어 데이타가 작업 전에 독립적으로 나눠질 수 없고 데이타 처리 중에 또는 후에 가능하다면 어떻게 할 것인가?
- Quick sort