Main Content

이 번역 페이지는 최신 내용을 담고 있지 않습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.

parfor를 언제 사용할지 결정하기

MATLAB의 parfor 루프

MATLAB®에서 parfor 루프는 루프 본문의 일련의 명령문을 병렬로 실행합니다. MATLAB 클라이언트는 parfor 명령을 실행하고 MATLAB 워커가 병렬 풀의 워커에 대한 루프 반복을 병렬로 실행하도록 조율합니다. 클라이언트는 parfor가 연산을 수행하는 데 필요한 데이터를 워커로 보내며, 워커에서 대부분의 계산이 실행됩니다. 결과는 클라이언트로 다시 보내져 조합됩니다.

parfor 루프는 여러 MATLAB 워커가 동일한 루프를 동시에 계산할 수 있기 때문에 이와 비슷한 for 루프보다 훨씬 뛰어난 성능을 제공할 수 있습니다.

parfor 루프 본문의 각 실행을 반복이라고 합니다. MATLAB 워커는 특정 순서 없이 서로 독립적으로 반복을 실행합니다. 각 반복은 독립적이므로 반복이 어떤 식으로든 동기화된다는 보장은 없으며 동기화해야 할 필요 조차도 없습니다. 워커 개수가 루프 반복 수와 같을 경우 각 워커는 하나의 루프 반복을 수행합니다. 워커보다 반복이 많을 경우 일부 워커는 하나 이상의 루프 반복을 수행하게 되는데, 이 경우 워커는 통신 시간을 줄이기 위해 한 번에 여러 반복을 수신할 수 있습니다.

parfor를 언제 사용할지 결정하기

느린 for 루프가 있는 경우, parfor 루프가 유용할 수 있습니다. 다음과 같은 경우에 parfor 사용을 고려해 보십시오.

  • 실행 시간이 오래 걸리는 루프 반복이 있는 경우. 이 경우 여러 워커가 긴 반복을 동시에 실행할 수 있습니다. 반복 횟수가 워커 개수보다 많도록 하십시오. 그렇지 않으면 사용 가능한 모든 워커를 사용하지 않습니다.

  • 많은 루프 반복이 몬테카를로 시뮬레이션 또는 파라미터 스윕과 같이 간단한 계산으로 구성된 경우. parfor는 각 워커가 전체 반복 횟수의 일부를 실행하도록 루프 반복을 여러 그룹으로 분할합니다.

parfor 루프는 다음과 같은 경우에는 유용하지 않을 수 있습니다.

  • for 루프를 벡터화한 코드가 있는 경우. 일반적으로 코드 실행 속도를 높이려면 벡터화부터 수행해 보십시오. 자세한 내용은 벡터화 항목을 참조하십시오. 코드를 벡터화하면 멀티스레드 특성을 가진 많은 기본 MATLAB 라이브러리에서 제공하는 내장 병렬 처리를 활용할 수 있습니다. 그러나 벡터화된 코드를 사용하고 로컬 워커에만 액세스할 수 있는 경우에는 parfor 루프가 for 루프보다 느리게 실행될 수도 있습니다. parfor를 사용하려는 목적으로 벡터화된 코드를 되돌리려 하지 마십시오. 일반적으로 이 해결책은 잘 작동하지 않습니다.

  • 실행 시간이 짧은 루프 반복이 있는 경우. 이 경우 병렬 연산에 드는 오버헤드가 계산의 대부분을 차지합니다.

루프 내 반복이 다른 반복의 결과에 따라 달라지는 경우 parfor 루프를 사용할 수 없습니다. 각 반복은 서로 독립적이어야 합니다. 독립적인 루프를 처리하는 것에 대한 자세한 내용은 parfor 루프 반복이 서로 독립적이어야 함 항목을 참조하십시오. 이 규칙은 Reduction Variables를 사용하여 루프의 값을 누적하는 경우에는 적용되지 않습니다.

parfor를 언제 사용할지 결정할 때 병렬 연산에 드는 오버헤드를 고려하십시오. 병렬 연산에 드는 오버헤드에는 클라이언트와 워커 간의 통신, 조정 및 데이터 전송(데이터 송수신)에 필요한 시간이 포함됩니다. 반복 실행 속도가 빠른 경우 이 오버헤드는 전체 시간의 상당한 부분을 차지할 수 있습니다. 다음 두 가지 다른 유형의 루프 반복을 살펴보겠습니다.

  • 계산량이 많은 작업이 있는 for 루프. 이러한 루프는 일반적으로 parfor 루프로 변환하기에 적합합니다. 계산에 필요한 시간이 데이터 전송에 필요한 시간의 상당 부분을 차지하기 때문입니다.

  • 간단한 계산 작업이 있는 for 루프. 이러한 루프는 일반적으로 parfor 루프로 변환하기에 적합하지 않습니다. 데이터 전송에 필요한 시간이 계산에 필요한 시간에 비해 상당하기 때문입니다.

병렬 연산에 드는 오버헤드가 낮은 parfor의 예제

이 예제에서는 for 루프 내에 계산량이 많은 작업으로 시작합니다. for 루프는 느리므로 대신 parfor 루프를 사용하여 계산 속도를 높입니다. parforfor 루프 반복의 실행을 병렬 풀의 워커로 분할합니다.

Diagram showing a MATLAB client using a parfor-loop to divide work between three parallel workers.

이 예제에서는 행렬의 스펙트럼 반지름을 계산하고 for 루프를 parfor 루프로 변환합니다. 속도가 얼마나 향상되는지 측정하는 방법과 병렬 풀의 워커 간 데이터 전송량을 측정하는 방법을 알아봅니다.

  1. MATLAB 편집기에서 다음 for 루프를 입력합니다. tictoc을 추가하여 계산 시간을 측정합니다.

    tic
    n = 200;
    A = 500;
    a = zeros(n);
    for i = 1:n
        a(i) = max(abs(eig(rand(A))));
    end
    toc
  2. 스크립트를 실행하고 경과 시간을 확인합니다.

    Elapsed time is 31.935373 seconds.

  3. 스크립트에서 for 루프를 parfor 루프로 바꿉니다. ticBytestocBytes를 추가하여 병렬 풀의 워커 간 데이터 전송량을 측정합니다.

    tic
    ticBytes(gcp);
    n = 200;
    A = 500;
    a = zeros(n);
    parfor i = 1:n
        a(i) = max(abs(eig(rand(A))));
    end
    tocBytes(gcp)
    toc

  4. 4개의 워커에서 새 스크립트를 실행하고 코드를 다시 실행합니다. 병렬 풀을 시작하고 코드를 워커에서 사용 가능하도록 하는데 약간의 시간이 걸리기 때문에 첫 번째 실행이 두 번째 실행보다 느립니다. 두 번째 실행의 데이터 전송량과 경과 시간을 확인합니다.

    기본적으로 MATLAB은 로컬 컴퓨터에서 워커의 병렬 풀을 자동으로 엽니다.

    Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
    ...
                 BytesSentToWorkers    BytesReceivedFromWorkers
                 __________________    ________________________
    
        1        15340                  7024                   
        2        13328                  5712                   
        3        13328                  5704                   
        4        13328                  5728                   
        Total    55324                 24168                   
    
    Elapsed time is 10.760068 seconds. 
    4개의 워커에서 실행된 parfor는 이에 상응하는 for 루프 계산보다 약 3배 빠릅니다. 워커가 4개임을 감안하면 속도가 4배 빨라지는 것이 이상적이지만 그보다는 느립니다. 이는 데이터를 클라이언트에서 워커로 전송하고 다시 클라이언트로 전송하는 데 필요한 시간 등의 병렬 연산에 드는 오버헤드 때문입니다. ticBytestocBytes의 결과를 사용하여 전송된 데이터의 양을 살펴봅니다. 데이터 전송에 필요한 시간은 데이터 크기에 비례한다고 가정합니다. 이런 어림짐작을 통해 데이터 전송에 필요한 대략적인 시간을 확인하고 병렬 연산에 드는 오버헤드와 다른 parfor 루프 반복을 비교해볼 수 있습니다. 이 예제의 데이터 전송과 병렬 연산에 드는 오버헤드는 다음 예제에 비해 작습니다.

현재 예제는 병렬 연산에 드는 오버헤드가 낮아 parfor 루프로 변환하기 적합합니다. 병렬 연산에 드는 오버헤드가 높은 parfor의 예제 항목을 참조하여 이 예제를 다음 예제의 단순 루프 반복과 비교해 보십시오.

계산량이 많은 작업이 포함된 parfor 루프의 다른 예제는 중첩 parfor 루프와 중첩 for 루프 및 기타 parfor 요구 사항 항목을 참조하십시오.

병렬 연산에 드는 오버헤드가 높은 parfor의 예제

이 예제에서는 루프를 작성하여 간단한 사인파를 만듭니다. for 루프를 parfor 루프로 바꾼다고 계산 속도가 향상되지 않습니다. 이 루프는 반복이 많지 않고 실행 시간이 오래 걸리지 않으며 실행 속도가 향상이 되더라도 이를 알기 힘듭니다. 이 예제는 병렬 연산에 드는 오버헤드가 높아 parfor 루프로 변환하는 것이 적합하지 않습니다.

  1. 루프를 작성하여 사인파를 만듭니다. tictoc을 사용하여 경과 시간을 측정합니다.

    tic
    n = 1024;
    A = zeros(n);
    for i = 1:n
        A(i,:) = (1:n) .* sin(i*2*pi/1024);
    end
    toc
    Elapsed time is 0.012501 seconds.
  2. for 루프를 parfor 루프로 바꿉니다. ticBytestocBytes를 추가하여 병렬 풀의 워커 간 데이터 전송량을 측정합니다.

    tic
    ticBytes(gcp);
    n = 1024;
    A = zeros(n);
    parfor (i = 1:n)
        A(i,:) = (1:n) .* sin(i*2*pi/1024);
    end
    tocBytes(gcp)
    toc

  3. 4개의 워커에서 스크립트를 실행하고 코드를 다시 실행합니다. 병렬 풀을 시작하고 코드를 워커에서 사용 가능하도록 하는데 약간의 시간이 걸리기 때문에 첫 번째 실행이 두 번째 실행보다 느립니다. 두 번째 실행의 데이터 전송량과 경과 시간을 확인합니다.

                 BytesSentToWorkers    BytesReceivedFromWorkers
                 __________________    ________________________
    
        1        13176                 2.0615e+06              
        2        15188                 2.0874e+06              
        3        13176                 2.4056e+06              
        4        13176                 1.8567e+06              
        Total    54716                 8.4112e+06              
    
    Elapsed time is 0.743855 seconds.
    연속적인 for 루프의 경과 시간이 4개의 워커에서 실행된 parfor 루프의 경과 시간보다 훨씬 짧습니다. 이 경우 for 루프를 parfor 루프로 바꿔서 얻는 이점이 없습니다. 그 이유는 데이터 전송량이 이전 예제에서보다 훨씬 많기 때문입니다. 병렬 연산에 드는 오버헤드가 낮은 parfor의 예제 항목을 참조하십시오. 현재 예제에서는 병렬 연산에 드는 오버헤드가 계산 시간의 상당 부분을 차지합니다. 따라서 사인파 반복은 parfor 루프로 변환하는 것에 적합하지 않습니다.

이 예제에서는 병렬 연산에 드는 오버헤드가 높은 계산을 parfor 루프로 변환하는 것에 이점이 없는 이유를 설명합니다. 코드 속도 향상에 대한 자세한 내용은 for 루프를 parfor 루프로 변환하기 항목을 참조하십시오.

참고 항목

| |

관련 항목