SIMD 확장

Visual C++는 현재 OpenMP 2.0 표준을 지원합니다. 그러나 Visual Studio 2019에서도 SIMD 기능을 제공합니다.

참고 항목

SIMD를 사용하려면 스위치를 -openmp:experimental 사용할 때 추가 OpenMP 기능을 사용할 수 없는 스위치로 컴파일합니다 -openmp .

스위치 하위 -openmp항목은 -openmp:experimental 모든 OpenMP 2.0 기능이 해당 용도에 포함되어 있음을 의미합니다.

자세한 내용은 Visual Studio에서 C++ OpenMP로 SIMD 확장을 참조 하세요.

Visual C++의 OpenMP SIMD

OpenMP 4.0 표준에 도입된 OpenMP SIMD는 벡터 친화적 루프를 만드는 것을 목표로 합니다. 컴파일러는 루프 앞에 지시문을 사용하여 simd 벡터 종속성을 무시하고, 루프를 가능한 한 벡터 친화적으로 만들고, 동시에 여러 루프 반복을 실행하려는 사용자의 의도를 준수할 수 있습니다.

    #pragma omp simd
    for (i = 0; i < count; i++)
    {
        a[i] = a[i-1] + 1;
        b[i] = *c + 1;
        bar(i);
    }

Visual C++는 유사한 비 OpenMP 루프 pragma와 유사 #pragma vector 하게 #pragma ivdep제공하지만 OpenMP SIMD를 사용하면 컴파일러가 다음과 같이 더 많은 작업을 수행할 수 있습니다.

  • 항상 현재 벡터 종속성을 무시할 수 있습니다.
  • /fp:fast 은 루프 내에서 사용하도록 설정됩니다.
  • 함수 호출이 있는 외부 루프 및 루프는 벡터 친화적입니다.
  • 중첩된 루프를 하나의 루프로 병합하여 벡터 친화적으로 만들 수 있습니다.
  • 거친 다중 스레딩 및 세분화된 벡터를 사용하도록 설정하는 하이브리드 가속 #pragma omp for simd .

벡터 친화적 루프의 경우 벡터 지원 로그 스위치를 사용하지 않는 한 컴파일러는 자동으로 다시 기본.

    cl -O2 -openmp:experimental -Qvec-report:2 mycode.cpp
    mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200'
    mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200'
    mycode.cpp(96) : info C5001: Omp simd loop vectorized

비벡터 친화적 루프의 경우 컴파일러는 각 메시지를 발급합니다.

    cl -O2 -openmp:experimental mycode.cpp
    mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200'
    mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200'

OpenMP SIMD 지시문은 다음 절을 사용하여 벡터 지원을 향상시킬 수도 있습니다.

지시문 설명
simdlen(length) 벡터 레인 수를 지정합니다.
safelen(length) 벡터 종속성 거리를 지정합니다.
linear(list[ : linear-step]) 루프 유도 변수에서 배열 구독으로의 선형 매핑입니다.
aligned(list[ : alignment]) 데이터의 맞춤입니다.
private(list) 데이터 민영화를 지정합니다.
lastprivate(list) 마지막 반복의 최종 값을 사용하여 데이터 민영화를 지정합니다.
reduction(reduction-identifier:list) 사용자 지정된 축소 작업을 지정합니다.
collapse(n) 병합 루프 중첩입니다.

참고 항목

비효과적 SIMD 절은 컴파일러에서 경고와 함께 구문 분석되고 무시됩니다.

예를 들어 다음 코드를 사용하면 경고가 발생합니다.

   #pragma omp simd simdlen(8)
   for (i = 0; i < count; i++)
   {
       a[i] = a[i-1] + 1;
       b[i] = *c + 1;
       bar(i);
   }
   warning C4849: OpenMP 'simdlen' clause ignored in 'simd' directive

예시

OpenMP SIMD 지시문은 사용자에게 컴파일러 make 루프를 벡터 친화적으로 지시하는 방법을 제공합니다. OpenMP SIMD 지시문으로 루프에 주석을 추가하면 사용자는 여러 루프 반복을 동시에 실행하려고 합니다.

예를 들어 다음 루프는 OpenMP SIMD 지시문으로 주석이 추가됩니다. 루프 반복 중에는 [i]에서 [i-1]로의 이전 종속성이 있으므로 완벽한 병렬 처리는 없지만 SIMD 지시문으로 인해 컴파일러는 여전히 첫 번째 문의 연속 반복을 하나의 벡터 명령으로 압축하고 병렬로 실행할 수 있습니다.

    #pragma omp simd
    for (i = 0; i < count; i++)
    {
        a[i] = a[i-1] + 1;
        b[i] = *c + 1;
        bar(i);
    }

따라서 컴파일러가 각 원래 루프 반복의 순차적 동작을 유지하므로 다음과 같은 변환된 루프 벡터 형식이 유효 합니다. 즉, a[i] 이후에 a[-1]실행되고, b[i] 이후 a[i] 이고 호출이 bar 마지막으로 수행됩니다.

    for (i = 0; i < count; i+=4)
    {
        a[i:i+3] = a[i-1:i+2] + 1;
        b[i:i+3] = *c + 1;
        bar(i);
        bar(i+1);
        bar(i+2);
        bar(i+3);
    }

메모리 참조가 별칭이나 b[i]별칭일 수 있는 경우 루프 밖으로 메모리 참조 *ca[i] 이동하는 것은 합법적이지 않습니다. 또한 순차적 종속성을 깨뜨리는 경우 하나의 원래 반복 내에서 문을 다시 정렬하는 것은 합법적이지 않습니다. 예를 들어 다음과 같은 변환된 루프는 적합하지 않습니다.

    c = b;
    t = *c;
    for (i = 0; i < count; i+=4)
    {
        a[i:i+3] = a[i-1:i+2] + 1;
        bar(i);            // illegal to reorder if bar[i] depends on b[i]
        b[i:i+3] = t + 1;  // illegal to move *c out of the loop
        bar(i+1);
        bar(i+2);
        bar(i+3);
    }

참고 항목

/openmp(OpenMP 2.0 지원 사용)