[Ch 7] 7.2.2 fork join 프레임워크 제대로 사용하기

kkambbak1·2023년 4월 21일
0

https://github.com/BanditBool2/ReadingRecord/issues/38

생각보다 간단한 내용이었다. 재사용의 의미가 진짜 말 그대로 재사용이었다.


7.2 포크/조인 프레임 워크

포크조인 프레임워크는 서브태스크를 스레드 풀의 작업자 스레드 에 분산 할당하는 ExecutorService인터페이스를 구현한다.

RecursiveTask활용

compute()를 구현해야함.

Divide&Conquer의 병렬화버전으로 보면 된다.

  1. 분할

    ForkJoinSumClculator를 ForkJoinPool로 전달하면, 풀의 스레드가 ForkJoinSumCalculator의 compute()를 실행하면서 작업을 수행한다.

    1. compute 메소드는 병렬로 실행할 만큼 태스크의 크기가 작아졌는지 확인, 크면 반으로 분할해서 두 개의 ForkJoinSumCalculator로 할당.
    2. ForkJoinPool이 새로 생성된 ForkJoinSumCalculator를 실행한다.

    이 과정이 조건(수행 항목이 만개 이상)을 만족할때까지 재귀적으로 반복하며 태스크 분할

  1. 각 서브태스크는 순차적으로 처리되며 루트에서 역순으로 방문하여 처리.
  2. 결과 합치기

포크조인프레임워크를 제대로 사용하는 법

  1. 두 서브태스크가 모두 시작된 다음 join을 호출해야 한다.
    a. join메서드를 태스크에 호출하면 태스크가 생산하는 결과가 준비될 때까지 호출자를 블록시키기 때문.

  2. RecursiveTask 내에서는 ForkJoinPool의 invoke()를 사용하지 말아야 한다.
    a. 대신 compute()나 fork()를 직접 호출 가능
    b. 순차 코드에서 병렬 계산 시작시에만 invoke() 사용

  3. 둘 다 fork()를 호출 하는 것 보다 한쪽에는 compute()를 호출하는 것이 효율적이다.
    a. fork() 메서드를 호출해서 ForkJoinPool의 일정을 조절할 수 있다.
    b. 한 태스크에는 같은 스레드를 재사용 할 수 있으므로 풀에서 불필요한 태스크 할당을 피할 수 있다.

  4. 디버깅이 어렵다. stack trace가 도움이 되지 않는다.
    a. 한 쪽에는 fork, 다른 하나는 compute가 호출 되므로

  5. 멀티코어에 포크/조인 프레임워크 사용이 순차 처리보다 무조건 빠를거라는 생각은 버려라.
    a. 각 태스크의 실행시간이 포킹하는데 드는 시간보다 길어야 한다.
    b. 또한 컴파일러 최적화는 병렬 버전보다는 순차 버전에 집중될 수 있다는 사실도 기억

profile
윤성

0개의 댓글