【问题标题】:Issues with clEnqueueMapBuffer in OpenCLOpenCL 中的 clEnqueueMapBuffer 问题
【发布时间】:2016-08-19 11:13:20
【问题描述】:

我正在开发一个在 OpenCL 中实现递归光线追踪的程序。 要运行内核,我必须选择设备:与系统集成的 Intel 设备和 Nvidia GeForce 显卡。

当我使用第一台设备运行项目时,没有问题;它运行正确并显示算法的结果很好。

但是当我尝试在 Nvidia 设备上运行它时,它在具有同步缓冲区映射的回调函数中崩溃。

它崩溃的代码部分如下:

clEnqueueNDRangeKernel(   queue, kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);

// 7. Look at the results via synchronous buffer map.
cl_float4 *ptr = (cl_float4 *) clEnqueueMapBuffer( queue, buffer, CL_TRUE, CL_MAP_READ, 0, kWidth * kHeight * sizeof(cl_float4), 0, NULL, NULL, NULL ); 
cl_float *viewTransformPtr = (cl_float *) clEnqueueMapBuffer( queue, viewTransform, CL_TRUE, CL_MAP_WRITE, 0, 16 * sizeof(cl_float), 0, NULL, NULL, NULL ); 
cl_float *worldTransformsPtr = (cl_float *) clEnqueueMapBuffer( queue, worldTransforms, CL_TRUE, CL_MAP_WRITE, 0, 16 * sizeof(cl_float), 0, NULL, NULL, NULL ); 

memcpy(viewTransformPtr, viewMatrix, sizeof(float)*16);
memcpy(worldTransformsPtr, sphereTransforms, sizeof(float)*16);

clEnqueueUnmapMemObject(queue, viewTransform, viewTransformPtr, 0, 0, 0);
clEnqueueUnmapMemObject(queue, worldTransforms, worldTransformsPtr, 0, 0, 0);

unsigned char* pixels = new unsigned char[kWidth*kHeight*4];
for(int i=0; i <  kWidth * kHeight; i++){
    pixels[i*4] = ptr[i].s[0]*255;
    pixels[i*4+1] = ptr[i].s[1]*255;
    pixels[i*4+2] = ptr[i].s[2]*255;
    pixels[i*4+3] = 1;
}

glBindTexture(GL_TEXTURE_2D, 1);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D(GL_TEXTURE_2D, 0, 4, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
delete [] pixels;

对 clEnqueueMapBuffer 的最后两次调用返回与 CL_OUT_OF_RESOURCES 匹配的错误 -5,但我相信缓冲区的大小是正确的。

【问题讨论】:

    标签: opencl nvidia


    【解决方案1】:

    根据 CL 规范,从回调中调用 CL 阻塞调用是未定义的。您的代码可能是正确的,但您不能从回调中使用它。在具有集成内存的英特尔平台中,映射是无操作的,因此不会失败。

    CL spec: clSetEventCallbacks

    调用昂贵的系统例程的行为,OpenCL API 调用 创建上下文或命令队列,或阻止 OpenCL 操作 下面的列表,在回调中是未定义的。

    clFinish
    clWaitForEvents
    blocking calls to clEnqueueReadBuffer, clEnqueueReadBufferRect, clEnqueueWriteBuffer, and clEnqueueWriteBufferRect
    blocking calls to clEnqueueReadImage and clEnqueueWriteImage
    blocking calls to clEnqueueMapBuffer and clEnqueueMapImage
    blocking calls to clBuildProgram
    

    如果应用程序需要等待从 以上 l 是在回调中,请使用非阻塞形式 函数,并为其分配一个完成回调以完成剩余部分 你的工作。请注意,当回调(或其他代码)入队时 命令队列的命令,这些命令不需要开始 执行直到队列被刷新。在标准用法中,阻塞 enqueue 调用通过隐式刷新队列来充当此角色。自从 回调中不允许阻塞调用,那些回调 命令队列上的入队命令应该调用 clFlush 在返回之前排队或安排稍后调用 clFlush 另一个线程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-05
      • 1970-01-01
      • 1970-01-01
      • 2012-12-12
      • 2020-06-27
      • 2011-04-27
      • 2018-01-10
      相关资源
      最近更新 更多