取自OpenCL by Action
以下代码实现了图中所示的目标。 它创建了两个缓冲区对象,并使用clEnqueueCopyBuffer将Buffer 1的内容复制到Buffer 2。
然后clEnqueueMapBuffer将缓冲区2的内容映射到主机内存,memcpy将映射的内存传输到数组。
我的问题是我的代码是否仍然有效如果我没有在代码中写下以下几行:
err = clSetKernelArg(kernel, 0, sizeof(cl_mem),
&buffer_one);
err |= clSetKernelArg(kernel, 1, sizeof(cl_mem),
&buffer_two);
queue = clCreateCommandQueue(context, device, 0, &err);
err = clEnqueueTask(queue, kernel, 0, NULL, NULL);
内核是空白的,它什么都不做。设置内核参数和排队任务的需要是什么?
...
float data_one[100], data_two[100], result_array[100];
cl_mem buffer_one, buffer_two;
void* mapped_memory;
...
buffer_one = clCreateBuffer(context,
CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
sizeof(data_one), data_one, &err);
buffer_two = clCreateBuffer(context,
CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
sizeof(data_two), data_two, &err);
err = clSetKernelArg(kernel, 0, sizeof(cl_mem),
&buffer_one);
err |= clSetKernelArg(kernel, 1, sizeof(cl_mem),
&buffer_two);
queue = clCreateCommandQueue(context, device, 0, &err);
err = clEnqueueTask(queue, kernel, 0, NULL, NULL);
err = clEnqueueCopyBuffer(queue, buffer_one,
buffer_two, 0, 0, sizeof(data_one),
0, NULL, NULL);
mapped_memory = clEnqueueMapBuffer(queue,
buffer_two, CL_TRUE, CL_MAP_READ, 0,
sizeof(data_two), 0, NULL, NULL, &err);
memcpy(result_array, mapped_memory, sizeof(data_two));
err = clEnqueueUnmapMemObject(queue, buffer_two,
mapped_memory, 0, NULL, NULL);
}
...
答案 0 :(得分:0)
我认为调用enqueueTask的目的是确保数据实际驻留在设备上。当使用CL_MEM_COPY_HOST_PTR
标志时,内存仍然保留在主机端,直到内核需要它为止。因此,将任务排入队列可确保将内存带到设备。这可能也发生在某些设备上,而不是其他设备上。
您可以通过检测代码并测量运行任务所花费的时间来测试此理论,无论是在任务有参数时,还是在没有参数时。如果任务在参数上花费的时间要长得多,那么很可能会发生这种情况。