2

JOCLを使用したJavaのOpenCLでのバックプロップ学習で、フィードフォワード多層パーセプトロンの実装に問題があります。計算フェーズのカーネルコードは次のとおりです。

    #pragma OPENCL EXTENSION cl_khr_fp64 : enable
    __kernel void Neuron(__global const double *inputPatterns,
                           __global double *weights,
                           __global const int *numInputs,
                           __global const int *activation,
                           __global const double *bias,
                           __global const int *usingBias,
                           __global double *values,
                           __global const int *maxNumFloats,
                           __global const int *patternIndex,
                           __global const int *inputPatternSize,
                           __global const int *indexOffset,
                           __global const int *isInputNeuron,
                           __global const int *inputs)
    {
       int gid = get_global_id(0);
       double sum = 0.0;
       for(int i = 0; i < numInputs[gid+indexOffset[0]]; i++)
       {
           sum += values[inputs[(gid+indexOffset[0]) * maxNumFloats[0] + i]] *
                   weights[(gid+indexOffset[0]) * maxNumFloats[0] + i];
       }
       if(usingBias[gid+indexOffset[0]])
           sum += bias[gid+indexOffset[0]];
       if(isInputNeuron[gid+indexOffset[0]])
           sum += inputPatterns[gid+indexOffset[0]+(patternIndex[0] * inputPatternSize[0])];
       if(activation[gid+indexOffset[0]] == 1)
           sum = 1.0 / (1.0 + exp(-sum));
       values[gid + indexOffset[0]] = sum;
    }

基本的に、私はネットワークの各レイヤーに対してこのカーネルを実行します。最初のレイヤーには「入力」がないため、ループは実行されません。ただし、最初のレイヤーは入力ノードレイヤーであるため、入力パターンから関連する値を追加します。これは正常に実行され、この時点で値を読み戻すことができます。

ただし、SECONDレイヤー(入力があり、最初のレイヤーのすべてのノードがあります)を実行しようとすると、clFinish()を呼び出すとエラーCL_INVALID_COMMAND_QUEUEが返されます。このエラーは、ドライバーのクラッシュと回復と関連している場合があります。私は(たとえばここで)これがTDRタイムアウトの問題である可能性があることを読み、制限を引き上げようとしましたが、これが違いを生んでいるかどうかはわかりません。

clSetKernelArg()を呼び出して、愚かなことをチェックしていますが、コード内で明らかに何かを見つけられる人はいますか?forループが含まれているため、エラーが2番目のレイヤーに導入されているように見えます...必要に応じてパラメーターを明確にすることができますが、最初の投稿には少しやり過ぎのようです。

また、私はこのコードがおそらくどこでも有能なコーダーを侮辱することになることを十分に承知していますが、気軽に炎上してください:P

編集:ホストコード:

    //Calc
    for(int k = 0; k < GPUTickList.length; k++)
    {
        clFlush(clCommandQueue);
        clFinish(clCommandQueue);
        //If input nodes
        if(k == 0)
            //Set index offset to 0
            GPUMapIndexOffset.asIntBuffer().put(0, 0);
        else
            //Update index offset
            GPUMapIndexOffset.asIntBuffer().put(0,
                GPUMapIndexOffset.asIntBuffer().get(0) + GPUTickList[k-1]);
        //Write index offset to GPU buffer
        ret = clEnqueueWriteBuffer(clCommandQueue, memObjects[12], CL_TRUE, 0,
                Sizeof.cl_int, Pointer.to(GPUMapIndexOffset.position(0)), 0, null, null);             
        //Set work size (width of layer)
        global_work_size[0] = GPUTickList[k];
        ret = clEnqueueNDRangeKernel(clCommandQueue, kernel_iterate, 1,
            global_work_offset, global_work_size, local_work_size,
            0, null, null);
    }

編集2:完全なコードをpastebinにアップロードしました。

4

2 に答える 2

2

解決しました。[0]でインデックス付けされたすべてのものを、バッファーではなく、ストレートカーネルパラメーターにすることでエラーを修正しました。明らかに、ハードウェアは、バッファの特定の要素に一度にアクセスする多くのものを好まない。

于 2012-04-04T19:41:31.083 に答える