【问题标题】:OpenCL - Kernel crashes on the second runOpenCL - 第二次运行时内核崩溃
【发布时间】:2013-09-16 04:13:09
【问题描述】:

我正在尝试运行第一次运行但第二次运行时崩溃的代码。导致崩溃的函数是 Octree_GPU 类的一部分,是这样的:

int Octree_GPU::runCreateNodeKernel(int length)
{
      cl_uint nodeLength;
      if(nodeNumsArray[length-1] == 0)
            nodeLength = nodeAddArray[length-1];
      else
            nodeLength = nodeAddArray[length-1]+8;
      nodeArray = (cl_uint*)malloc(sizeof(cl_uint)*nodeLength);
      nodePointsArray = (cl_int*)malloc(sizeof(cl_uint)*nodeLength);
      startIndexArray = (cl_int*)malloc(sizeof(cl_int)*nodeLength);

      d_nodeAdd = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_uint)*length, NULL, &err);
      d_nodeArray = clCreateBuffer(context,CL_MEM_READ_WRITE, sizeof(cl_uint)*temp_length, NULL, &err);
      d_numPoints = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_uint)*length, NULL, &err);
      d_pointIndex = clCreateBuffer(context, CL_MEM_READ_WRITE,sizeof(cl_uint)*length,NULL, &err);
      d_nodePointsArray = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int)*temp_length, NULL, &err);
      d_nodeIndexArray = clCreateBuffer(context,CL_MEM_READ_WRITE, sizeof(cl_int)*temp_length, NULL, &err);

      err |= clEnqueueWriteBuffer(commands, d_nodeAdd, CL_TRUE, 0, sizeof(cl_uint)*length, nodeAddArray, 0, NULL,NULL);
      err |= clEnqueueWriteBuffer(commands, d_numPoints,CL_TRUE, 0, sizeof(cl_uint)*length,numPointsArray,0,NULL,NULL);
      err |= clEnqueueWriteBuffer(commands, d_pointIndex, CL_TRUE, 0, sizeof(cl_uint)*length,pointStartIndexArray,0, NULL, NULL);
      clFinish(commands);

      err  = clSetKernelArg(createNodeKernel, 0, sizeof(cl_mem), &d_odata);
      err |= clSetKernelArg(createNodeKernel, 1, sizeof(cl_mem), &d_nodeNums);
      err |= clSetKernelArg(createNodeKernel, 2, sizeof(cl_mem), &d_nodeAdd);
      err |= clSetKernelArg(createNodeKernel, 3, sizeof(cl_mem), &d_numPoints);
      err |= clSetKernelArg(createNodeKernel, 4, sizeof(cl_mem), &d_pointIndex);
      err |= clSetKernelArg(createNodeKernel, 5, sizeof(cl_mem), &d_nodeArray);
      err |= clSetKernelArg(createNodeKernel, 6, sizeof(cl_mem), &d_nodePointsArray);
      err |= clSetKernelArg(createNodeKernel, 7, sizeof(cl_mem), &d_nodeIndexArray);
      clFinish(commands);

      if(err != CL_SUCCESS) {
            printf("Cannot set Kernel Arg \n");
            exit(1);
      }
      size_t global_size[1] = {limit-1};
      err = clEnqueueNDRangeKernel(commands, createNodeKernel, 1, NULL, global_size, NULL, 0, NULL, NULL);
      if(err != CL_SUCCESS) {
            printf(" Kernel does not work \n");
            exit(1);
      }
      clFinish(commands);

      err = clEnqueueReadBuffer(commands, d_nodeArray, CL_TRUE, 0, sizeof(cl_uint)*temp_length, nodeArray, 0, NULL, NULL);
      err|= clEnqueueReadBuffer(commands, d_nodePointsArray, CL_TRUE, 0, sizeof(cl_int)*nodeLength, nodePointsArray, 0, NULL, NULL);
      err|= clEnqueueReadBuffer(commands, d_nodeIndexArray, CL_TRUE, 0, sizeof(cl_int)*nodeLength, startIndexArray, 0, NULL, NULL);
      clFinish(commands);

      clReleaseMemObject(d_nodeAdd);
      clReleaseMemObject(d_numPoints);
      clReleaseMemObject(d_nodeArray);
      clReleaseMemObject(d_nodePointsArray);
      clFinish(commands);
      return 0;
}

请注意,d_odata 和 d_nodeNums 已在之前的函数中声明。内核代码如下:

__kernel void createNode(__global int* uniqueCode, __global int* nodeNums,__global int* nodeAdd, __global int* numPoints, __global int* pointIndex,__global int* nodeArray, __global int* nodePoints,__global int* nodeIndex)
{
    int ig = get_global_id(0);
    int add;
    int num = uniqueCode[ig];
    int pt = numPoints[ig];
    int ind = pointIndex[ig];
    int temp,j;
    if(nodeNums[ig] == 8) 
    {
           for(int i=0;i<8;i++)
           {
                    temp = ((int)num/10)*10+i;
                    add = nodeAdd[ig] + i;
                    nodeArray[add] = temp;
                    nodePoints[add] = select(0, pt, temp==num);
                    nodeIndex[add] = select(-1, ind, temp==num);
                    barrier(CLK_LOCAL_MEM_FENCE);
           }
    }
    else
    {
           j = num % 10;
           nodeAdd[ig] = nodeAdd[ig-1];
           add = nodeAdd[ig]+j;
           nodePoints[add] = pt;
           nodeIndex[add] = ind;
           barrier(CLK_LOCAL_MEM_FENCE);
    }

}

我试图找出原因,但没有成功。我可能忽略了一些非常简单的事情。感谢您的帮助。

【问题讨论】:

    标签: crash kernel opencl


    【解决方案1】:

    我不是 100% 确定这是导致崩溃的原因,但你写的地方

    if(nodeNums[ig] == 8) 
    {
           for(int i=0;i<8;i++)
           {
                    barrier(CLK_LOCAL_MEM_FENCE);
           }
    }
    else
    {
           barrier(CLK_LOCAL_MEM_FENCE);
    }
    

    这意味着工作组中的不同线程将执行不同数量的屏障,这可能会导致挂起/崩溃。屏障(带有 CLK_LOCAL_MEM_FENCE)用于同步对本地内存的访问,因此组中的所有工作项必须在继续之前执行此操作

    在非崩溃说明中,当您的意思是 CLK_GLOBAL_MEM_FENCE(确保全局内存访问跨线程可见)时,您似乎正在使用 CLK_LOCAL_MEM_FENCE(确保本地内存访问跨线程可见)

    还有

    nodeAdd[ig] = nodeAdd[ig-1];
    

    对于 ig == 0 不正确。这可能不会导致实际崩溃(因为不幸的是,我发现 OpenCL 可能非常宽容),但值得修复

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多