- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写的一些 openCL 代码遇到问题。
我编写了一组实用函数,以从我使用它的地方删除一些样板代码。测试方法从一开始就运行并且工作得很好,代码如下:
void openCLtest(char *arg_program, char *arg_device)
{
cl_int ret;
cl_device_id device_id = getDeviceId(atoi(arg_program), atoi(arg_device));
cl_context context = get_cl_context(&device_id);
cl_command_queue queue = get_cl_command_queue(&context, &device_id);
cl_kernel kernel = compileCLkernel(&context, &device_id, "src/hello.cl", "hello");
cl_mem memobj = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(char), NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Allocate Buffer\n");
exit(1);
}
ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to set kernel Arg\n");
exit(1);
}
ret = clEnqueueTask(queue, kernel, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Enqueue Task\n");
exit(1);
}
ret = clFinish(queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to wait for finish\n");
exit(1);
}
char string[MEM_SIZE];
ret = clEnqueueReadBuffer(queue, memobj, CL_TRUE, 0, MEM_SIZE * sizeof(char), string, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to read buffer\n");
exit(1);
}
printf("CL Produced: %s\n", string);
ret = clFlush(queue);
ret = clFinish(queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Wait for test queue to finish\n");
exit(1);
}
ret = clReleaseKernel(kernel);
ret = clReleaseMemObject(memobj);
ret = clReleaseCommandQueue(queue);
ret = clReleaseContext(context);
}
这段代码运行良好,然后我将代码提取到更多函数中,这些函数可用于我正在编写的真正的 openCL。
相同的原理已应用于其余代码,但这次不起作用。
主要:
openCLtest(argv[2], argv[3]); //This is the code above and works great
cl_device_id device_id = getDeviceId(atoi(argv[2]), atoi(argv[3]));
cl_context context = get_cl_context(&device_id);
cl_command_queue queue = get_cl_command_queue(&context, &device_id);
....
double *coords_3D = cl_extrude_coords(&device_id, &context, &queue, coords_2D, nodes, LAYERS, LAYER_HEIGHT);
cl_extrude_coords:
double *cl_extrude_coords(cl_device_id* device_id, cl_context* context, cl_command_queue* queue, double *coords, int nodes, int layers, double layer_height)
{
cl_int ret;
cl_kernel extrude_coords = compileCLkernel(context, device_id, "src/OpenCL_Kernels/extrude_coords.cl", "extrude_coords");
cl_mem coords_2d = clCreateBuffer(*context, CL_MEM_READ_ONLY, sizeof(coords) / sizeof(coords[0]), NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Create coords_2d CL Buffer %d\n", ret);
exit(1);
}
cl_mem result = clCreateBuffer(*context, CL_MEM_WRITE_ONLY, sizeof(double) * nodes * 3 * layers, NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Create result CL Buffer %d\n", ret);
exit(1);
}
ret = clEnqueueWriteBuffer(*queue, coords_2d, CL_TRUE, 0, sizeof(coords) / sizeof(coords[0]), (const void *)&coords, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed enqueue coords_2d write to buffer %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 0, sizeof(cl_mem), (void *)&coords_2d);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument coords_2d %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 1, sizeof(cl_mem), (void *)&result);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument result CL Buffer %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 2, sizeof(double), (void *)&layer_height);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument layers %d\n", ret);
exit(1);
}
size_t gWorkSize[] = {nodes, layers};
cl_event clEvent;
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, &clEvent);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Enqueue Extrude Coordinates Kernel\n");
exit(1);
}
double *res = (double *)malloc(sizeof(double) * nodes * 3 * layers);
ret = clFinish(*queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to wait for queue to finish in extrude_coords %d\n", ret);
exit(1);
}
ret = clEnqueueReadBuffer(*queue, result, CL_TRUE, 0, sizeof(double) * nodes * 3 * layers, (void *)res, 1, &clEvent, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Enqueue the extrude_coords result buffer read %d\n", ret);
exit(1);
}
ret = clReleaseKernel(extrude_coords);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release kernel\n");
exit(1);
}
ret = clReleaseMemObject(coords_2d);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release result memory object\n");
exit(1);
}
ret = clReleaseMemObject(result);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release result memory object\n");
exit(1);
}
return res;
}
cl 内核:
#pragma OPENCL EXTENSION cl_khr_fp64: enable
__kernel void extrude_coords(__global const double * coords, __global double * res, const double layer_height){
uint i=get_global_id(0);
uint j=get_global_id(1);
uint layers=get_global_size(0);
res[3*(i*layers + j)] = coords[2*i];
res[3*(i*layers + j) + 1] = coords[2*i + 1];
res[3*(i*layers + j) + 2] = layer_height * j;
}
但是,此函数不起作用,在调用 clFinish(queue) 时抛出以下错误。
Failed to wait for queue to finish in extrude_coords -36
查一下,我可以看到-36是CL_INVALID_COMMAND_QUEUE
。如果我不从此处退出,则会在读取缓冲区时抛出错误,错误代码 -5,CL_OUT_OF_RESOURCES
。
我不确定出了什么问题。该代码测试时节点和层的值分别为151731和101。我不确定这是否与此有关。
有没有人对可能出现的问题以及如何解决它有任何想法,或者甚至对这种代码结构是否是一个好主意有任何建议。该计划是通过传递队列、上下文和设备 ID,每个函数都可以生成并执行自己的内核,以在不再需要队列等时在程序结束时释放它们。
任何帮助将不胜感激,我已经被这个问题困扰了几个小时了。
编辑:
此后我尝试将 extrude_coords 中的 clEnqueueNDRange
的调用约定更改为
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize[0], NULL, 0, NULL, &clEvent);
按照答案中的建议,但这不起作用。使用 printf("%d\n", &gWorkSize == &gWorkSize[0]);
进行测试表明这两个指针在功能上是相同的,因此这不是问题。
然后我继续修改测试 openCL 代码以使用 clEnqueueNDRange
而不是 clEnqueueTask,如下所示:
size_t gWorkSize[] = {1, 1};
// ret = clEnqueueTask(queue, kernel, 0, NULL, NULL);
ret = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, NULL);
这仍然一切正常,所以其他东西显然是错误的......我仍然不确定是什么......
最佳答案
sizeof(coords) / sizeof(coords[0])
不会给出 C/C++ 中的数组大小。最好用sizeof(coords)*elementsInCoords
并传入elementsInCoords
。或者,将坐标设置为 std::vector<>
并传递它,因为您可以从中获取数据指针和大小。
关于c - 调用 clFinish() 时 OpenCL 无效命令队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22051427/
OpenCL 1.1 规范说: cl_int clEnqueueBarrier(cl_command_queue command_queue) clEnqueueBarrier is a synchr
OpenCL clFinish() API 调用会阻塞,直到命令队列上的所有命令都已完成执行。相关函数, clFlush() ,据说 Issues all previously queued Open
我有多个内核,它们按顺序启动,如下所示: clEnqueueNDRangeKernel(..., kernel1, ...); clEnqueueNDRangeKern
我正在编写的一些 openCL 代码遇到问题。 我编写了一组实用函数,以从我使用它的地方删除一些样板代码。测试方法从一开始就运行并且工作得很好,代码如下: void openCLtest(char *
我正在制作一个 opencl 包装器,它为每个缓冲区使用不同的命令队列。 所有读/写操作都是非阻塞的。 问题是,其中一个读/写操作未发出(从分析器看来)。 CodeXL 探查器显示漏洞。我在图片上做了
我是 opencl 的新手,但我对 GPU 编程并不陌生。我需要确保我的 cpu 和 gpu 设备相互同步。看来我应该使用 clFinish(cl::commandqueue queue),但我使用的
我是 OpenCL 的新手,但有一件事让我很烦,目前我用 clFlush 结束每个 OpenCL 函数,这是根据标准阻塞。有没有办法通过返回 std::future 或编写手写的 my::craft:
我正在尝试在 GPU 上运行内核并在主机 (CPU) 上进行额外的计算。我看到了这个效果: 只有内核需要大约 2000 毫秒: clEnqueueNDRangeKernel ... clFinish
我是一名优秀的程序员,十分优秀!