2

次のようにインスタンス化する 2D 配列 C があります。

const int wA = 16;
float * C[wA];
for(int i = 0; i < hA; i++)
{
C[i] = new float[hA];
for(int i2 = 0; i2 < hA; i2++)
    C[i][i2] = 0;
}

/* looks like this:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
*/

C で動作するカーネルを作成します。

__kernel void simpleMultiply(__global float* outputC, 
                            int widthA, 
                            int heightA, 
                            int widthB, 
                            int heightB, 
                            __global float * inputA, 
                            __global float * inputB)
{
    int row = get_global_id(1);
    int col = get_global_id(0);
    float sum = 0.0f;
    for(int i = 0; i < widthA; i++)
    {
        sum += inputA[row*widthA+i] * inputB[i*widthB+col];
    }
    outputC[row*widthB+col] = sum;
}

そしてすべてがうまくいきます。コンテキストの設定からバッファの作成、カーネル、プログラム、clEnqueueNDRangeKernel、clEnqueueReadBuffer などの作成まで、ステータスとして CL_SUCCESS を取得します。

しかし、出力を読みに行くとクラッシュします。

status = clEnqueueNDRangeKernel(cmdQueue, kernel, 2, NULL, globalws, localws, 0, NULL, NULL);
cout << "\nclEnqueueNDRangeKernel: " << (status == CL_SUCCESS ? "SUCCESS" : "FAIL"); // prints SUCCESS
status = clEnqueueReadBuffer(cmdQueue, bufferC, CL_TRUE, 0, wC*hC*sizeof(float), (void*)C, 0, NULL, NULL);
cout << "\nclEnqueueReadBuffer: " << (status == CL_SUCCESS ? "SUCCESS" : "FAIL"); // prints SUCCESS
cout << "\nC[0][0]: " << C[0][0]; // <--crash

ここに画像の説明を入力

私は OpenCL と同じように C++ を初めて使用するので、C++ の配列とポインターの理解が不十分であることが原因である可能性があります。

コード全体はこちら

4

1 に答える 1

4

配列

float * C[wA];

float *ポインターの 1D 配列です。したがって、連続した行と列を持つ 2D 配列をメモリ内に作成していません。しかし、行へのポインターの配列を作成しました。

そのため、ホスト配列 C でフラット化し、カーネルで行うのと同じ方法でそれにインデックスを付ける必要があります。

float * C;

c = new float[ha * ha]; // Create a  contiguous memory area  to be addressed  in a 2D pattern

memset( C, 0, ha * ha  * sizeof(float) ); // Set all bytes to zero


...

カーネルの実行後に C 配列をアドレス指定できるようになりました

cout << C[ icolumn  + irow * ha ];  // icolumn and irow are your row and columns indices  
于 2013-07-01T14:36:18.840 に答える