gpt4 book ai didi

c - 调用 clFinish() 时 OpenCL 无效命令队列

转载 作者:行者123 更新时间:2023-11-30 15:37:50 28 4
gpt4 key购买 nike

我正在编写的一些 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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com