2017-05-22 11 views
0

私はOpenACCを使用してのblock diagonal matricesに取り組んでいます。
コードを順番に実行すると、分解が正しく行われますが、OpecACCディレクティブで実行すると、分解を実行するときに間違った結果が得られます。OpenACC - ネストされたループの不思議な動作

LU分解が(hereLUPSolve関数を参照)、そのタイプのネストされたループを含む:

for (unsigned int i = 0; i < N; i++) 
    for (unsigned int k = 0; k < i; k++) 

ネストされたループのこのタイプは、並列領域内routine seqディレクティブで使用される場合、デバイスは常に管理する表示しますi=0k<iの条件のために可能ではない可能性があります)でもネストされたループに入ります。私はOpenACCのないコードを実行したときに私が得る

x = 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 

しかし、正しいもの(:

#pragma acc routine seq 
void test (int* x, int const n) { 
    for (unsigned int i = 0; i < n; i++) { 
     x[i] = -1; 
     for (unsigned int k = 0; k < i; k++) 
     x[i] = k < i; 
    } 
} 

int main () { 
    unsigned const n(4); 
    unsigned const nb(3); 
    int x[nb*n]; 
    #pragma acc parallel loop copyout(x[:nb*n]) 
    for (unsigned int b = 0; b < nb; b++) 
     test(x+b*n,n); 
    // display x 
} 

私が得る結果はこの1つである:

は、私はそれをチェックするために簡単なコードを作りました)次のようになります。

x = -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 

とき012それは、ネストされたループに入るべきではありませんので、私は何か間違ったことしなければなりません...
プラスループを並列領域に直接置くと(関数呼び出しを使用せずに)うまく動作します。

+0

は私はこのタイプのネストされたループとも試みたが、非常に奇妙です: 'のために(INT I = N-1、I> = 0; i--){(INT kに対する= I + 1。 (i = n-1; i> = 0; for n-1);これは次のように変更されます。 同じ奇妙な動作が起こり、デバイスは 'i = n-1'のネストループに入ります...' 0 <0'はネストされたループに当てはまります...私はちょうど私が間違っていることを知らない、それは私のループの状態のどこかにあるはずです... –

答えて

2

kとiが両方ともゼロのときでも常に内側ループを実行するコンパイラコードジェネレータの問題のように見えます。私は問題報告書(TPR#24317)を提出し、それを私たちのコンパイラエンジニアに送って、さらに評価しました。回避策として、内部ループに「if」チェックを追加します。

% cat test.cpp 
#include <stdio.h> 
#include <stdlib.h> 

#pragma acc routine seq 
void test (int* x, int const n) { 
    for (unsigned int i = 0; i < n; i++) { 
     x[i] = -1; 
     for (unsigned int k = 0; k < i; k++) { 
     if (k < i) 
      x[i] = (k<i); 
     } 
    } 
} 

int main () { 
    unsigned const n(4); 
    unsigned const nb(3); 
    int x[nb*n]; 
    #pragma acc parallel loop copyout(x[:nb*n]) 
    for (unsigned int b = 0; b < nb; b++) 
     test(x+b*n,n); 

    for (int i=0; i <nb; ++i) { 
    for (int j=0; j <n; ++j) { 
    printf("%d:%d %d\n", i,j, x[i*n+j]); 
    } } 
    exit(0); 
} 
% pgc++ -acc -Minfo=acc -ta=tesla:cc60 test.cpp; a.out 
test(int *, int): 
     5, Generating acc routine seq 
     Generating Tesla code 
main: 
    18, Generating copyout(x[:]) 
     Accelerator kernel generated 
     Generating Tesla code 
     20, #pragma acc loop gang, vector(3) /* blockIdx.x threadIdx.x */ 
0:0 -1 
0:1 1 
0:2 1 
0:3 1 
1:0 -1 
1:1 1 
1:2 1 
1:3 1 
2:0 -1 
2:1 1 
2:2 1 
2:3 1 
+0

私は狂っていました!私は 'if'チェックで終わった –

関連する問題