TBB를 사용하여 "꼬리 호출"재귀를 다중 스레드하는 방법

atb

tbb를 사용하여 기존 재귀 알고리즘을 다중 스레드하려고합니다. 단일 스레드 버전은 꼬리 호출 재귀를 사용하며 구조적으로 다음과 같습니다.

void my_func() {
    my_recusive_func (0);
}

bool doSomeWork (int i, int& a, int& b, int& c) {
    // do some work
}

void my_recusive_func (int i) {
    int a, b, c;
    bool notDone = doSomeWork (i, a, b, c);
    if (notDone) {
        my_recusive_func (a);
        my_recusive_func (b);
        my_recusive_func (c);
    }
}

나는 tbb 초보자이므로 첫 번째 시도는 parallel_invoke 함수를 사용했습니다.

void my_recusive_func (int i) {
    int a, b, c;
    bool notDone = doSomeWork (i, a, b, c);
    if (notDone) {
        tbb::parallel_invoke (
                [a]{my_recusive_func (a);},
                [b]{my_recusive_func (b);},
                [c]{my_recusive_func (c);});
    }
}

이것은 작동하고 단일 스레드 버전보다 빠르게 실행되지만 코어 수에 따라 잘 확장되지 않는 것 같습니다. 내가 목표로 삼고있는 머신은 16 개의 코어 (32 개의 하이퍼 스레드)를 가지고 있으므로이 프로젝트에서는 확장 성이 매우 중요하지만,이 버전은 해당 머신에서 기껏해야 약 8 배의 속도 향상을 얻고 알고리즘이 실행되는 동안 많은 코어가 유휴 상태로 보입니다.

내 이론은 tbb가 parallel_invoke 후 자식 작업이 완료되기를 기다리고 있으므로 불필요하게 대기하는 동안 많은 작업이있을 수 있습니다. 이것이 유휴 코어를 설명 할 수 있습니까? 자녀를 기다리지 않고 부모 작업이 반환되도록 할 수있는 방법이 있습니까? 나는 아마도 이와 같은 것을 생각하고 있었지만 스케줄러에 대해 아직 충분히 알지 못하여 이것이 괜찮은지 아닌지 알 수 없습니다.

void my_func()
{
    tbb::task_group g;
    my_recusive_func (0, g);
    g.wait();
}

void my_recusive_func (int i, tbb::task_group& g) {
    int a, b, c;
    bool notDone = doSomeWork (i, a, b, c);
    if (notDone) {
        g.run([a,&g]{my_recusive_func(a, g);});
        g.run([b,&g]{my_recusive_func(b, g);});
        my_recusive_func (c, g);
    }
}

내 첫 번째 질문은 tbb::task_group::run()스레드로부터 안전합니까? 나는 문서에서 그것을 알아낼 수 없었다. 또한 이것에 대해 더 좋은 방법이 있습니까? 대신 저수준 스케줄러 호출을 사용해야할까요?

(컴파일하지 않고이 코드를 입력 했으므로 오타를 용서하십시오.)

아치 D. 로비슨

여기에는 두 가지 질문이 있습니다.

  1. task_group :: run의 TBB 구현은 스레드로부터 안전합니까? 예. (우리는 이것을 더 명확하게 문서화해야합니다).
  2. 많은 스레드가 동일한 task_group 에서 메소드 run ()을 호출하도록 확장 가능합니까? 아니요. (Microsoft 문서에이 내용이 어딘가에 언급되어 있다고 생각합니다.) 그 이유는 task_group이 중앙 집중식 경합 지점이되기 때문입니다. 구현에서 가져 오기 및 추가 일뿐이지만 영향을받는 캐시 라인이 바운스해야하기 때문에 궁극적으로 확장 할 수 없습니다.

일반적으로 task_group에서 적은 수의 작업을 생성하는 것이 가장 좋습니다. 재귀 병렬 처리를 사용하는 경우 각 수준에 고유 한 task_group을 제공합니다. 성능은 parallel_invoke를 사용하는 것보다 나을 것 같지는 않습니다.

저수준 tbb :: task 인터페이스가 최선의 방법입니다. tasK :: execute가 tail-call 태스크에 대한 포인터를 반환하는 트릭을 사용하여 꼬리 재귀를 코딩 할 수도 있습니다.

그러나 나는 유휴 스레드에 대해 약간 우려합니다. 스레드를 바쁘게 유지하기에 충분한 작업이 있는지 궁금합니다. 먼저 작업 기간 분석을 고려하십시오 . 인텔 컴파일러 (또는 gcc 4.9)를 사용하는 경우 먼저 Cilk 버전으로 실험 해 볼 수 있습니다. 속도가 빨라지지 않으면 낮은 수준의 tbb :: task 인터페이스도 도움이되지 않을 것이므로 더 높은 수준의 문제 (작업 및 범위)를 조사해야합니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

함수 호출을 반환하는 함수를 문서화하는 방법 (꼬리 호출 최적화를 위해)

분류에서Dev

꼬리 호출 최적화 (TCO)를 사용하는 숫자 배열을 합산하는 재귀 함수를 작성하려면 어떻게해야합니까?

분류에서Dev

꼬리 호출을 지원하기 위해 ackermann 함수의 변형을 변환하는 방법은 무엇입니까?

분류에서Dev

꼬리 호출 최적화가 재귀 호출 이외의 호출에 적용됩니까?

분류에서Dev

왜 이런 종류의 피보나치 꼬리 호출이 Haskell의 순수 트리 재귀보다 빠르게 실행됩니까?

분류에서Dev

Swift에서 다중 스레드를 사용하는 방법

분류에서Dev

OpenMP를 사용하여 다중 스레드 (10 개 이상의 스레드)에서 파일을 여는 방법

분류에서Dev

다중 스레드 환경에서 시퀀스를 사용하는 방법

분류에서Dev

스레드를 사용하여 MPRemoteCommandCenter로 다음 노래를 재생하는 방법은 무엇입니까?

분류에서Dev

postgres를 사용하여 다른 레코드 매핑을 위해 재귀 모드에서 하위 범주 ID를 얻는 방법은 무엇입니까?

분류에서Dev

Racket에서 람다 만 사용하여 재귀를 만드는 방법은 무엇입니까?

분류에서Dev

더미 변수를 사용하여 다중 회귀 분석 데이터를 시뮬레이션하는 방법

분류에서Dev

var를 사용하여 모든 재귀 호출을 중단하는 방법은 무엇입니까?

분류에서Dev

다중 스레드를 bash하는 방법?

분류에서Dev

Collectl 재귀를 중지하는 방법 ?? 다시 시작 하시겠습니까?

분류에서Dev

타이머와 다른 스레드를 사용하여 코드를 원활하게 실행하는 방법

분류에서Dev

재귀를 사용하여 n 차원 배열에 액세스하는 방법

분류에서Dev

재귀를 사용하여 목록에 함수를 적용하는 방법

분류에서Dev

재귀를 적용하는 방법

분류에서Dev

중복 레코드없이 DataTable.Load (DataReader)를 사용하여 DataGridView를 다시로드하는 방법

분류에서Dev

재귀를 사용하여 이진 검색을 만드는 방법

분류에서Dev

재귀 함수를 사용하여 ArrayList를 반환하는 방법

분류에서Dev

XPath를 사용하여 XML에서 재귀 요소를 검색하는 방법

분류에서Dev

중간 재귀 결과를 저장하는 방법

분류에서Dev

'requestAnimationFrame'으로 재귀 루프를 중지하는 방법

분류에서Dev

C에서 잠시 후 재귀를 중지하는 방법

분류에서Dev

swift를 사용하여 스레드가 실행 중이거나 완료되었는지 확인하는 방법

분류에서Dev

재귀 또는 다른 방법을 사용하여 LCM (1 to N), N> 2를 어떻게 구현합니까?

분류에서Dev

GTest를 사용하여 다중 스레드 테스트를 여러 번 반복하는 올바른 방법은 무엇입니까?

Related 관련 기사

  1. 1

    함수 호출을 반환하는 함수를 문서화하는 방법 (꼬리 호출 최적화를 위해)

  2. 2

    꼬리 호출 최적화 (TCO)를 사용하는 숫자 배열을 합산하는 재귀 함수를 작성하려면 어떻게해야합니까?

  3. 3

    꼬리 호출을 지원하기 위해 ackermann 함수의 변형을 변환하는 방법은 무엇입니까?

  4. 4

    꼬리 호출 최적화가 재귀 호출 이외의 호출에 적용됩니까?

  5. 5

    왜 이런 종류의 피보나치 꼬리 호출이 Haskell의 순수 트리 재귀보다 빠르게 실행됩니까?

  6. 6

    Swift에서 다중 스레드를 사용하는 방법

  7. 7

    OpenMP를 사용하여 다중 스레드 (10 개 이상의 스레드)에서 파일을 여는 방법

  8. 8

    다중 스레드 환경에서 시퀀스를 사용하는 방법

  9. 9

    스레드를 사용하여 MPRemoteCommandCenter로 다음 노래를 재생하는 방법은 무엇입니까?

  10. 10

    postgres를 사용하여 다른 레코드 매핑을 위해 재귀 모드에서 하위 범주 ID를 얻는 방법은 무엇입니까?

  11. 11

    Racket에서 람다 만 사용하여 재귀를 만드는 방법은 무엇입니까?

  12. 12

    더미 변수를 사용하여 다중 회귀 분석 데이터를 시뮬레이션하는 방법

  13. 13

    var를 사용하여 모든 재귀 호출을 중단하는 방법은 무엇입니까?

  14. 14

    다중 스레드를 bash하는 방법?

  15. 15

    Collectl 재귀를 중지하는 방법 ?? 다시 시작 하시겠습니까?

  16. 16

    타이머와 다른 스레드를 사용하여 코드를 원활하게 실행하는 방법

  17. 17

    재귀를 사용하여 n 차원 배열에 액세스하는 방법

  18. 18

    재귀를 사용하여 목록에 함수를 적용하는 방법

  19. 19

    재귀를 적용하는 방법

  20. 20

    중복 레코드없이 DataTable.Load (DataReader)를 사용하여 DataGridView를 다시로드하는 방법

  21. 21

    재귀를 사용하여 이진 검색을 만드는 방법

  22. 22

    재귀 함수를 사용하여 ArrayList를 반환하는 방법

  23. 23

    XPath를 사용하여 XML에서 재귀 요소를 검색하는 방법

  24. 24

    중간 재귀 결과를 저장하는 방법

  25. 25

    'requestAnimationFrame'으로 재귀 루프를 중지하는 방법

  26. 26

    C에서 잠시 후 재귀를 중지하는 방법

  27. 27

    swift를 사용하여 스레드가 실행 중이거나 완료되었는지 확인하는 방법

  28. 28

    재귀 또는 다른 방법을 사용하여 LCM (1 to N), N> 2를 어떻게 구현합니까?

  29. 29

    GTest를 사용하여 다중 스레드 테스트를 여러 번 반복하는 올바른 방법은 무엇입니까?

뜨겁다태그

보관