这个OpenCL内核导致错误CL_INVALID_COMMAND_QUEUE怎么样?

时间:2012-04-03 21:16:52

标签: neural-network opencl

我在实现前馈MultiLayer感知器方面遇到了问题,使用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。有时此错误与驱动程序崩溃和恢复相结合。我已经读过(例如here)这可能是TDR超时的问题,并试图提高限制但不确定这是否有任何区别。

我正在调用clSetKernelArg()来检查任何愚蠢的东西,但是有人能在代码中发现任何明显的东西吗?由于包含for循环,似乎错误是在第二层中引入的......如果需要,我可以澄清任何参数,但对于初始帖子来说似乎有点过分。

另外,我完全清楚这段代码可能是对各地有能力的编码人员的侮辱,但请随意火上浇油: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

2 个答案:

答案 0 :(得分:2)

解决。修复了错误,使用[0]索引的所有内容都是直接内核参数,而不是缓冲区。很明显,硬件不喜欢很多东西一次访问缓冲区的一个特定元素。

答案 1 :(得分:1)

我不确定你在循环之上的内容..你是否使用除此循环之外的队列?以下是您可能想要尝试的内容。

//flush + finish if you need to before the loop, otherwise remove these lines
clFlush(clCommandQueue);
clFinish(clCommandQueue);

cl_event latestEvent;
//Calc
for(int k = 0; k < GPUTickList.length; k++)
{
    //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, &latestEvent);
    clWaitForEvents(1, &latestEvent);
}