0

私は C++ で opencl 用の dotproduct カーネルを作成しましたが、ベクトル長 4096 で動作しています (12k 要素を試しても問題なく動作しています) が、ベクトル長を 16k 要素に増やすと、結果は無限大になり、小さな浮動小数点数を超えることはありません。番号。明らかにリークなどがありますが、n<16k 要素では問題なく動作します。16k 要素と 4 バイトはそれぞれ 64kB になり、3 つのバッファの合計は 192kB になり、これは GPU のメモリの 1/1000 にもなりません。ホスト コード (C#) の同じリダクション アルゴリズムと結果を比較すると、ホストの結果は予想どおり小さいです。無限大を構築するための精度エラーもありません(特定の有限値に制限されることさえあります)。

DLL 呼び出しを介して C# から C++ に渡されるカーネル (Ln= ローカル ワーク サイズ、n= グローバル ワーク サイズ) は次のとおりです。

"__kernel void SkalarCarpim(__global float * v1, __global float * v2, __global float * v3)" +
            "{" +
            "    int i = get_global_id(0);" +
            "    int j = get_local_id(0);" +
            "    __local float biriktirici [" + Ln.ToString() + "];" +
            "    barrier(CLK_LOCAL_MEM_FENCE);" +
            "    biriktirici[j]=v1[i]*v2[i];" +
            "    barrier(CLK_LOCAL_MEM_FENCE);" +
            "    barrier(CLK_GLOBAL_MEM_FENCE);" +
            "    float toplam=0.0f;" +
            "    if(j==0)" +
            "    {" +
            "        for(int k=0;k<"+Ln.ToString()+";k++)"+ // reduction
            "        {"+
            "             toplam+=biriktirici[k];"+
            "        }"+
            "    }" +
            "    barrier(CLK_GLOBAL_MEM_FENCE);" +
            "    v3[i]=toplam;" +
            "    barrier(CLK_GLOBAL_MEM_FENCE);" +
            "    toplam=0.0f;" +
            "    for(int k=0;k<"+(n/Ln).ToString()+";k++)" + 
            "    {" +
            "         toplam+=v3[k*"+Ln.ToString()+"];       " + // sum of temporary sums
            "    }" +
            "    v3[i]=toplam;"+
            "}";

C++ Opencl バッファは次のとおりです。

buf1=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
buf2=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
buf3=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
//CL_MEM_READ_ONLY makes same error, tried some other too, no solution :(

バッファの送信方法は次のとおりです。

komutSirasi.enqueueWriteBuffer(buf1,CL_TRUE,0,sizeof(cl_float)*N,v1);
komutSirasi.enqueueWriteBuffer(buf2,CL_TRUE,0,sizeof(cl_float)*N,v2);
//CL_TRUE makes a blocking action so waits until finished

実行:

 komutSirasi.enqueueNDRangeKernel(kernel,0,Global,Local);
 //I got this from an example and I dont know if it is blocking or not.

結果バッファの取得方法は次のとおりです(すべての要素が結果であり、未完成であることはわかっています):

komutSirasi.enqueueReadBuffer(buf3,CL_TRUE,0,sizeof(cl_float) * N,v3);
//CL_TRUE makes a blocking action so waits until finished

質問: C++ Opencl に飛び込む前に行う必要がある設定はありますか? これは、Java/Aparapi/Jocl では問題ではありませんでした。

Khronos のサイトからの Opencl 1.2 ヘッダーと、AMD Opencl.lib + Opencl.dll を使用すると、役立つ場合があります (ターゲット デバイスは HD7870)。

4

1 に答える 1