다음을 통해 공유


자동 병렬화 및 자동 벡터화

자동 평행화 도우미 및 자동 벡터화 도우미는 코드의 루프 성능을 자동으로 향상시키기 위해 설계되었습니다.

자동 평행화 도우미

/Qpar 컴파일러 스위치를 사용하면 코드에서 루프를 자동으로 병렬화할 수 있습니다. 기존 코드를 변경하지 않고 이 플래그를 지정하면 컴파일러는 코드를 평가하여 평행화에서 이점을 얻을 수 있는 루프를 찾습니다. 많은 작업을 수행하지 않아 평행화의 이점을 얻지 못하는 루프가 있을 수 있고 불필요한 모든 평행화가 스레드 풀 생성, 추가 동기화 또는 성능 향상보다는 성능을 저하시키는 기타 처리를 발생시킬 수 있으므로 컴파일러는 평행화할 루프를 선택하는 데 다소 신중합니다. 예를 들어 루프의 상한값이 컴파일 타임에 알려지지 않은 다음 예를 고려할 수 있습니다.

void loop_test(int u) {
   for (int i=0; i<u; ++i)
      A[i] = B[i] * C[i];
}

작은 값일 수 있으므로 u 컴파일러는 이 루프를 자동으로 병렬 처리하지 않습니다. 그러나 u가 항상 큰 값이 되는 것을 아는 경우 사용자는 이를 평행화하려 할 수 있습니다. 자동 병렬 처리를 사용하도록 설정하려면 병렬 처리할 스레드 수가 있는 n #pragma 루프(hint_parallel(n))를 지정합니다. 다음 예에서 컴파일러는 8개 스레드에 걸쳐 루프를 평행화하려고 합니다.

void loop_test(int u) {
#pragma loop(hint_parallel(8))
   for (int i=0; i<u; ++i)
      A[i] = B[i] * C[i];
}

모든 pragma 지시문과 마찬가지로 대체 pragma 구문 __pragma(loop(hint_parallel(n))) 도 지원됩니다.

원하는 경우에도 컴파일러가 병렬 처리할 수 없는 몇 가지 루프가 있습니다. 예를 들면 다음과 같습니다.

#pragma loop(hint_parallel(8))
for (int i=0; i<upper_bound(); ++i)
    A[i] = B[i] * C[i];

upper_bound() 함수는 호출될 때마다 변경될 수 있습니다. 상한을 알 수 없으므로 컴파일러는 이 루프를 병렬화할 수 없는 이유를 설명하는 진단 메시지를 내보낼 수 있습니다. 다음 예에서는 평행화할 수 있는 루프, 평행화할 수 없는 루프, 명령 프롬프트에서 사용할 컴파일러 구문 및 각 명령줄 옵션에 대한 컴파일러 구문을 보여 줍니다.

int A[1000];
void test() {
#pragma loop(hint_parallel(0))
    for (int i=0; i<1000; ++i) {
        A[i] = A[i] + 1;
    }

    for (int i=1000; i<2000; ++i) {
        A[i] = A[i] + 1;
    }
}

다음 명령어를 사용하여 컴파일 시:

cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:1

출력 결과:

--- Analyzing function: void __cdecl test(void)
d:\myproject\mytest.cpp(4) : loop parallelized

다음 명령어를 사용하여 컴파일 시:

cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:2

출력 결과:

--- Analyzing function: void __cdecl test(void)
d:\myproject\mytest.cpp(4) : loop parallelized
d:\myproject\mytest.cpp(4) : loop not parallelized due to reason '1008'

두 개의 서로 다른 /Qpar-report(자동 병렬 변환기 보고 수준) 옵션 간의 출력 차이가 있습니다. /Qpar-report:1은 공적으로 평행화된 루프에 대해서만 평행화 도우미 메시지를 출력합니다. /Qpar-report:2는 성공 및 실패한 루프 평행화 둘 모두에 대해 평행화 도우미 메시지를 출력합니다.

이유 코드 및 메시지에 대한 자세한 내용은 벡터라이저 및 병렬 변환기 메시지를 참조 하세요.

자동 벡터화 도우미

자동 벡터화 도우미는 코드의 루프를 분석하고 가능한 경우 대상 컴퓨터에서 벡터 레지스터 및 명령을 사용하여 루프를 실행합니다. 이를 통해 코드 성능을 향상시킬 수 있습니다. 컴파일러는 /arch 스위치에 따라 Intel 또는 AMD 프로세서의 SSE2, AVX 및 AVX2 명령 또는 ARM 프로세서의 NEON 지침을 대상으로 합니다.

자동 벡터화 도우미는 /arch 스위치로 지정한 것과는 다른 명령을 생성할 수 있습니다. 이러한 명령은 런타임 검사를 통해 코드가 제대로 실행되는지 확인됩니다. 예를 들어 /arch:SSE2를 컴파일하는 경우 SSE4.2 명령을 내보낼 수 있습니다. 런타임 검사는 대상 프로세서에서 SSE4.2를 사용할 수 있는지 확인한 후 프로세서가 해당 명령을 지원하지 않을 경우 비 SSE4.2 버전의 루프로 건너뜁니다.

기본적으로 자동 벡터화 도우미는 사용할 수 있게 설정되어 있습니다. 벡터화에서 코드의 성능을 비교하려는 경우 #pragma 루프(no_vector)를 사용하여 지정된 루프의 벡터화를 사용하지 않도록 설정할 수 있습니다.

#pragma loop(no_vector)
for (int i = 0; i < 1000; ++i)
   A[i] = B[i] + C[i];

모든 pragma 지시문과 마찬가지로 대체 pragma 구문 __pragma(loop(no_vector)) 도 지원됩니다.

자동 병렬 변환기와 마찬가지로 /Qvec-report(Auto-Vectorizer Reporting Level) 명령줄 옵션을 지정하여 성공적으로 벡터화된 루프만/Qvec-report:1 보고하거나 성공적으로 벡터화된 루프와 실패한 루프를 모두 보고할 수 있습니다/Qvec-report:2.

이유 코드 및 메시지에 대한 자세한 내용은 벡터라이저 및 병렬 변환기 메시지를 참조 하세요.

벡터라이저가 실제로 작동하는 방식을 보여 주는 예제는 Project Austin Part 2 of 6: Page Curling을 참조 하세요.

참고 항목

loop
네이티브 코드의 병렬 프로그래밍
/Qpar(자동 병렬화 도우미)
/Qpar-report(자동 병렬화 도우미 보고 수준)
/Qvec-report(자동 벡터화 도우미 보고 수준)
벡터화 도우미 및 평행화 도우미 메시지