0

私は次のopenclコードを持っています:

__constant SomeConstants[] = { 5, 7, 242, 74 };

long aslong(__global int * arr, int offset) {
    return ... <CalculateLong> ...;
};

void calcSomething(__global int * numArray, int * result) {
    long tempArray[] = { numArray[0], numArray[1], numArray[2], numArray[3] };

    long x0 = (result[0] = aslong(numArray, 0)) + tempArray[0];
    long x1 = (result[1] = aslong(numArray, 8)) + tempArray[1];
    long x2 = (result[2] = aslong(numArray, 16)) + tempArray[2];
    long x3 = (result[3] = aslong(numArray, 32)) + tempArray[3];
    // do some calculations here
    result[0] = x0;
    result[1] = x1;
    result[2] = x2;
    result[3] = x3;

};

__kernel void calc(__global int * numArray, __global long * sum) {
    long arr[] = { SomeConstants[0], SomeConstants[1], SomeConstants[2], SomeConstants[3] };
    calcSomething(numArray, arr);
    sum[get_global_id(0)] = arr[0];
    sum[get_global_id(0)+1] = arr[1];
    sum[get_global_id(0)+2] = arr[2];
    sum[get_global_id(0)+3] = arr[3];
};

上記のコードは期待どおりに動作しますが、問題は、calcSomething に計算を追加できないことです。次のように calcSomethig に空のループを追加すると:

void calcSomething(__global int * numArray, int * result) {
    long tempArray[] = { numArray[0], numArray[1], numArray[2], numArray[3] };

    long x0 = (result[0] = aslong(numArray, 0)) + tempArray[0];
    long x1 = (result[1] = aslong(numArray, 8)) + tempArray[1];
    long x2 = (result[2] = aslong(numArray, 16)) + tempArray[2];
    long x3 = (result[3] = aslong(numArray, 32)) + tempArray[3];

    for (int i = 0; i < 18; i++) {}

    result[0] = x0;
    result[1] = x1;
    result[2] = x2;
    result[3] = x3;

};

result[0] と result[1] は正しい値を格納しますが、result[2] と result[3] は完全に間違っています。for ループをコメント アウトすることで、result[2] と 3 は正しくなります... for ループの呼び出し中に x0、x1、x2、および x3 に何が起こったのか分かりますか?

4

1 に答える 1

1

編集された回答:あなたの問題は操作にあります:

sum[get_global_id(0)] = arr[0];
sum[get_global_id(0)+1] = arr[1];
sum[get_global_id(0)+2] = arr[2];
sum[get_global_id(0)+3] = arr[3];

sum[]インデックスが重複するグローバル配列を使用しています。ただし、多くの作業項目が同じメモリを書き込み、未定義の結果が生成されます。オーバーラップを修正するか、グローバル変数に対してアトミック操作を実行する必要があります。

例:

 gid 0 -> Write to sum[0,1,2,3]
 gid 1 -> Write to sum[1,2,3,4]
 //....

ループはfor問題とはまったく関係ありません。マルチスレッド環境でさまざまなスケジュールの効果を確認しているだけです。しかし、それは問題の根本ではありません。

さらに編集: コードには、OpenCL に関連しない問題があります。OpenCL の唯一の問題は、既に上で説明されています。

C 変数が間違ってアドレス指定されたり、暗黙的にキャストされたりしてから間違って使用されている場所がたくさんあります。たとえば、aslong()8 つの連続する int を追加して long を作成しますが、long は 8int ではなく 8 バイトで作成されます。

于 2013-11-12T11:38:25.980 に答える