3

私は OpenCL プログラムに取り組んでいますが、実行ごとに出力が異なります。特定の実行の値をハードコードすると、実行ごとに出力が似ているため、引数をカーネルに渡すことに関係していると思います。

私のカーネルは次のようになります。

__kernel void sample_kernel(__global double *BufferA, int scalar1, int scalar2, int scalar3, ...) {

    for(int i = -1*scalar1; i < scalar1; i++) {
        for(int j = -1*scalar1; j < scalar1, j++) {
            if(scalar2 > 0 && scalar3 > 0) // do something.
        }
    }
}

そして、これは私がカーネル引数を設定する方法です:

int scalar1 = 1;
int scalar2 = 2;
int scalar3 = 3;

Samplekernel.setArg(0, d_BufferA);
Samplekernel.setArg(1, sizeof(int), &scalar1);
Samplekernel.setArg(2, sizeof(int), &scalar2);
Samplekernel.setArg(3, sizeof(int), &scalar3);

奇妙なことに、追加すると...

if(scalar1 != 1) scalar1 = 1;
if(scalar2 != 2) scalar2 = 2;
if(scalar3 != 3) scalar3 = 3;

...二重forループの前のカーネルでは、出力は正しいです。

Nvidia K20m GPU、OpenCL バージョン 1.1 でプログラムを実行しています。Nvidia C2075 でコードを実行すると、すべて正常に動作するように見えます...

問題が何であるかを知っている人はいますか?値が正しくコピーされていないか、上書きされているようですが、for ループの前にその値にアクセスしていません...

前もって感謝します!

4

1 に答える 1

2

int へのポインターを setArg に渡しているようです

Samplekernel.setArg(1, sizeof(int), &scalar1);

次に、カーネルパラメーターリストには、ポインターではなくintの値があります。

__kernel void sample_kernel(__global double *BufferA, int scalar1, ...

次のように、カーネル パラメーター リストでポインターを使用することもできます。

__kernel void sample_kernel(__global double *BufferA, global int *scalar1,

または-それが私が提案するものです.C++バインディング仕様でkernel.setArg(...)のバージョンを見つけることができなかったので、何らかの理由でkhronos.orgの実装でのみ-そのようにスカラーを直接コピーします:

Samplekernel.setArg(1, scalar1);

これには、バッファを引数として指定した場合のように、変数がグローバル空間ではなく、カーネルのプライベートメモリ空間で使用できるという利点もあります。

使用している Kernel::setArg のバージョンは値をコピーしない可能性があり、ホストにバインドされたカーネルにのみ使用される可能性がありますが、私はそれについて確信が持てません。

また、setArg の戻り値のエラーを確認することもできます。

于 2013-04-12T10:42:23.063 に答える