1

ICCで-opt-reportまたは-vec-reportオプションを使用して特定のファイルをコンパイルすると、特に次のメッセージが表示されます。

foo.c(226:7-226:7):VEC:function_foo:  loop was not vectorized: subscript too complex
foo.c(226): (col. 7) warning #13379: loop was not vectorized with "simd"
vectorization support: call to function absorbing_apply cannot be vectorized
loop was not vectorized: not inner loop
loop was not vectorized: unsupported loop structure
loop was not vectorized: subscript too complex

私はこれらのメッセージの意味を知っています。私が心配しているのは foo.c:226、ループがまったくないということです。実際、別の関数の呼び出しがあります。その関数には、ボリュームを介して動作し、iccが報告するときに実際に適切にベクトル化するループがいくつか含まれています。ただし、その関数を呼び出すと、貼り付けたものと同じメッセージが表示されます。

ループのない場所にベクトル化メッセージが表示されているため、iccは混乱しますか?それとも私が何かを誤解したのは私ですか?

編集:私は問題を半複製しました。今回、コンパイラーは、別の関数への呼び出しがあるコードの行をベクトル化したことを通知します(元の場合は逆であり、不可能であると通知します)。コードは次のとおりです。

 1 
 2 
 3 void foo(float *a, float *b, float *c, int n1, int n2, int n3, int ini3, int end3 ) {
 4    int i, j, k;
 5 
 6    for( i = ini3; i < end3; i++ ) {
 7       for( j = 0; j < n2; j++ ) {
 8        #pragma simd
 9        #pragma ivdep
10        for( k = 0; k < 4; k ++ ) {
11          int index = k + j*n1 + i*n1*n2;
12          a[index] = b[index] + 2* c[index];
13        }
14      }
15    }
16 
17    for( i = ini3; i < end3; i++ ) {
18       for( j = 0; j < n2; j++ ) {
19        #pragma simd
20        #pragma ivdep
21        for( k = n1-4; k < n1; k ++ ) {
22          int index = k + j*n1 + i*n1*n2;
23          a[index] = b[index] + 2* c[index];
24        }
25      }
26    }
27 
28   return;
29 }
30 int main(void){
31    int n1, n2, n3;
32    int ini3 = 20;
33    int end3 = 30;
34    n1 = n2 = n3 = 200;
35 
36    float *a = malloc( n1 * n2 * n3 * sizeof(float ));
37    float *b = malloc( n1 * n2 * n3 * sizeof(float ));
38    float *c = malloc( n1 * n2 * n3 * sizeof(float ));
39 
40    foo( a,b,c, n1, n2, n3, ini3, end3 );
41 
42    ini3 += 50;
43    end3 += 50;
44 
45    foo( a,b,c, n1, n2, n3, ini3, end3 );
46 
47    free(a); free(b); free(c);
48 
49   return 0;
50 }
51 

そして、ICCが40行目と45行目をベクトル化したと言っている最適化レポートの一部:

foo.c(40:4-40:4):VEC:main:  LOOP WAS VECTORIZED
loop was not vectorized: not inner loop
loop was not vectorized: not inner loop
LOOP WAS VECTORIZED
loop was not vectorized: not inner loop
loop was not vectorized: not inner loop
foo.c(45:4-45:4):VEC:main:  LOOP WAS VECTORIZED
loop was not vectorized: not inner loop
loop was not vectorized: not inner loop

これは正常ですか?

4

2 に答える 2

2

投稿した例では、への関数呼び出しfoo()がインライン化されています。インライン化された後、内部のループfoo()はベクトル化されます。

その結果、すべてのコードが40行目と45行目に「折りたたまれ」ます。vectorizo​​rがコードに触れるまでに、元々別の関数からのものであることがわかりません。

ベクトル化されていないと言う元の例では、同じ状況が当てはまります。関数呼び出しはインライン化されていますが、ベクトル化できないループが含まれています。


おそらく、ICCは関数呼び出しを通じて回線情報を保持できたはずです。ただし、関数がインライン化されるたびに、重複したベクトル化レポートが表示されます。さらに、それらはすべて同じ線を指します。それは間違いなくさらに混乱するでしょう。

于 2012-11-28T09:42:52.767 に答える
0

簡単なコーディングのヒント-次のような構造は使用しないでください。

for( i = ini3; i < end3; i++ ) {
   for( j = 0; j < n2; j++ ) {
   #pragma simd
   #pragma ivdep
   for( k = 0; k < 4; k ++ ) {
     int index = k + j*n1 + i*n1*n2;
     a[index] = b[index] + 2* c[index];
   }
   }
}

index最も内側のループの各反復でのステップで増分されることは明らかかもしれません1が、コンパイラのベクトライザーはそれを理解するのに苦労するかもしれません。より良い使用法:

for( i = ini3; i < end3; i++ ) {
   for( j = 0; j < n2; j++ ) {
      int base = (j + i*n2)*n1;
      for( k = base; k < base+4; k++ ) {
         a[k] = b[k] + 2* c[k];
      }
   }
}

今、何が起こっているのかは明らかであり、最も愚かなベクトライザーでさえそれを理解できるはずです(そしてコードはややきれいに見えます)。を使用する代わりに、#pragma ivdepコンパイラをより安心させ、C99修飾子を使用して重複しないメモリ領域をポイントします。abcrestrict

void foo(float *restrict a, float *restrict b, float *restrict c,
         int n1, int n2, int n3, int ini3, int end3) {
于 2012-12-01T15:42:57.467 に答える