문제

i Vectorization Optimization 문제가 있습니다.

3 개의 필드가 'red', 'green'및 'blue'라는 3 개의 필드가있는 struct pdst가 있습니다.
유형은 'char', '짧은'또는 'float'.This가 변경 될 수 있으며 변경할 수 없습니다.
theres는 이미지 [RGB] - 이미지가 이미지 층을 가리키는 3 개의 포인터의 배열을 나타내는 또 다른 어레이 PSRC입니다.
각 레이어는 IPP 평면 지향 이미지를 사용하여 구축됩니다 (즉, 각 평면은 독립적으로 형성됩니다 - 'ippimalloc_32f_c1') : http://software.intel.com/sites. / products/documentation/hpc/ipp/ippi/ippi_ch3/functn_malloc.html .

다음 코드에서 설명한대로 복사하고 싶습니다.

for(int y = 0; y < imageHeight; ++y)
{
    for(int x = 0; x < imageWidth; ++x)
    {
        pDst[x + y * pDstRowStep].red     = pSrc[0][x + y * pSrcRowStep];
        pDst[x + y * pDstRowStep].green   = pSrc[1][x + y * pSrcRowStep];
        pDst[x + y * pDstRowStep].blue    = pSrc[2][x + y * pSrcRowStep];
    }
} 
.

아직,이 양식에서 컴파일러는 코드를 벡터화 할 수 없습니다.
처음에는 다음과 같이 말합니다.

"루프가 벡터화되지 않았습니다. 벡터 의존성의 존재.".

#pragma ivdep을 사용하여 컴파일러를 돕는 경우 (의존성이 없기 때문에) 다음 오류가 발생합니다.

"루프가 vectorized가 아니 었습니다 : deleference 너무 복잡합니다.".

누구나 벡터화를 허용하는 방법을 가지고 있습니까? Intel Compiler 13.0을 사용합니다.
고마워.

업데이트 :

코드를 다음과 같이 편집하는 경우 :

Ipp32f *redChannel      = pSrc[0];
Ipp32f *greenChannel  = pSrc[1];
Ipp32f *blueChannel     = pSrc[2];
for(int y = 0; y < imageHeight; ++y)
{
    #pragma ivdep
    for(int x = 0; x < imageWidth; ++x)
    {
        pDst[x + y * pDstRowStep].red     = redChannel[x + y * pSrcRowStep];
        pDst[x + y * pDstRowStep].green   = greenChannel[x + y * pSrcRowStep];
        pDst[x + y * pDstRowStep].blue    = blueChannel[x + y * pSrcRowStep];
    }
}
.

'char'및 'short'의 출력 유형의 출력 유형은 Vecotization을 얻습니다.
그러나 'float'의 유형에 대해서는 그렇지 않습니다.
대신 다음 메시지가 나타납니다.

루프는 벡터화되지 않았지만 가능한하지만 비효율적 인 것 같습니다.

어떻게 될 수 있습니까?

도움이 되었습니까?

해결책

다음 코드에서 Pragma IVDEP를 사용하면 벡터 의존성을 분명히 무시하지만 컴파일러 휴리스틱 / 비용 분석이 루프를 벡터화하는 결론이 효율적이지 않다는 결론을 내리 었습니다.

Ipp32f *redChannel      = pSrc[0];
Ipp32f *greenChannel  = pSrc[1];
Ipp32f *blueChannel     = pSrc[2];
for(int y = 0; y < imageHeight; ++y)
{
    #pragma ivdep
    for(int x = 0; x < imageWidth; ++x)
    {
        pDst[x + y * pDstRowStep].red     = redChannel[x + y * pSrcRowStep];
        pDst[x + y * pDstRowStep].green   = greenChannel[x + y * pSrcRowStep];
        pDst[x + y * pDstRowStep].blue    = blueChannel[x + y * pSrcRowStep];
    }
}
.

소스에서 인접하지 않은 메모리 위치로의 연속 메모리 블록을 대상의 연속 메모리 위치를 복사하는 데 비효율적이기 때문에 비효율적이기 때문에 비효율적이기 때문입니다.그래서 여기에 산란이 있습니다.벡터화를 적용하고 비 벡터 화되는 버전과 비교하여 성능 향상이 있는지 확인하려면 아래 그림과 같이 Pragma IVDEP 대신 Pragma SimD를 사용하십시오.

#include<ipp.h>
struct Dest{
float red;
float green;
float blue;
};
void foo(Dest *pDst, Ipp32f **pSrc, int imageHeight, int imageWidth, int pSrcRowStep, int pDstRowStep){
    Ipp32f *redChannel      = pSrc[0];
    Ipp32f *greenChannel  = pSrc[1];
    Ipp32f *blueChannel     = pSrc[2];
    for(int y = 0; y < imageHeight; ++y)
    {
        #pragma simd
        for(int x = 0; x < imageWidth; ++x)
        {
            pDst[x + y * pDstRowStep].red     = redChannel[x + y * pSrcRowStep];
            pDst[x + y * pDstRowStep].green   = greenChannel[x + y * pSrcRowStep];
            pDst[x + y * pDstRowStep].blue    = blueChannel[x + y * pSrcRowStep];
        }
    }
    return;
}
.

해당 벡터화 보고서는 다음과 같습니다.

$ icpc -c test.cc -vec-report2
test.cc(14): (col. 9) remark: SIMD LOOP WAS VECTORIZED
test.cc(11): (col. 5) remark: loop was not vectorized: not inner loop
.

Pragma SimD에 대한 더 많은 문서는 https://software.intel.com/에서 사용할 수 있습니다.en-us / node / 514582 .

다른 팁

해당 라인을 따라 무언가가 작동해야합니다 (GeneracoDodiceTagcode 버전, 테스트되지 않음, __m128i 포인터가 올바르게 정렬되어야한다는 것을 명심하십시오!)

void interleave_16px_to_rgb0(__m128i *red, __m128i *green, __m128i *blue, __m128i *dest) {
  __m128i zero = _mm_setzero_si128();
  __m128i rg_0 = _mm_unpackhi_epi8(*red, *green);
  __m128i rg_1 = _mm_unpacklo_epi8(*red, *green);
  __m128i bz_0 = _mm_unpackhi_epi8(*blue, zero);
  __m128i bz_1 = _mm_unpacklo_epi8(*blue, zero);
  dest[0] = _mm_unpackhi_epi16(rg_0, bz_0);
  dest[1] = _mm_unpacklo_epi16(rg_0, bz_0);
  dest[2] = _mm_unpackhi_epi16(rg_1, bz_1);
  dest[3] = _mm_unpacklo_epi16(rg_1, bz_1);
}
.

이렇게하면 각 비행기에서 16 바이트가 걸립니다.

r0 r1 r2 ... r16
g0 g1 g2 ... g16
b0 b1 b2 ... b16
.

interleave leave와 같이 interive, char에서 시작하는 16x4 바이트를 작성하십시오.

r0 g0 b0 0 r1 g1 b1 0 r2 g2 b2 0 ... r16 g16 b16 0
.

다른 데이터 유형을 모두 인터리빙하기 위해 동일한 함수 계열을 사용할 수 있다는 것을 말하지 않고도됩니다.


업데이트 : 더 나은 아직, 이미 IPP가 있으므로 휠을 재발 명하는 대신 제공되는 것을 사용하려고 노력해야합니다.빠른 점검에서 ippicopy_8u_p3c3r 또는 ippicopy_8u_p4c4r이 찾고있는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top