我在采用OpenCL代码的YOLO中遇到性能问题。
该方法仅从设备中提取数据,第一次运行很慢,而在接下来的几个调用中很快。有通话记录,时间以微秒为单位:
clEnqueueMapBuffer 144469
memcpy 2
clEnqueueUnmapMemObject 31
clEnqueueMapBuffer 466
memcpy 103
clEnqueueUnmapMemObject 14
clEnqueueMapBuffer 468
memcpy 106
clEnqueueUnmapMemObject 17
第一次调用是使用1字节副本(其中memcpy需要2微秒)。
内存是通过代码分配的:
if (!x)
x = (float*) calloc(n, sizeof(float));
buf.ptr = x;
cl_int clErr;
buf.org = clCreateBuffer(opencl_context, CL_MEM_READ_WRITE |
CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR, buf.len * buf.obs, buf.ptr, &clErr);
下一个提取数据的代码:
#ifdef BENCHMARK
clock_t t;
double time_taken;
t = clock();
#endif
cl_int clErr;
void* map = clEnqueueMapBuffer(opencl_queues[opencl_device_id_t], x_gpu.mem, CL_TRUE, CL_MAP_READ,
0, x_gpu.len * x_gpu.obs, 0, NULL, NULL, &clErr);
#ifdef BENCHMARK
t = clock() - t;
time_taken = ((double)t);
printf("clEnqueueMapBuffer\t%d\n", (int)time_taken);
t = clock();
#endif
if (clErr != CL_SUCCESS)
printf("could not map array to device. error: %s\n", clCheckError(clErr));
memcpy(x, map, (n - x_gpu.off) * x_gpu.obs);
#ifdef BENCHMARK
t = clock() - t;
time_taken = ((double)t);
printf("memcpy\t%d\n", (int)time_taken);
t = clock();
#endif
clErr = clEnqueueUnmapMemObject(opencl_queues[opencl_device_id_t], x_gpu.mem, map, 0, NULL, NULL);
if (clErr != CL_SUCCESS)
printf("could not unmap array from device. error: %s\n", clCheckError(clErr));
#ifdef BENCHMARK
t = clock() - t;
time_taken = ((double)t);
printf("clEnqueueUnmapMemObject\t%d\n", (int)time_taken);
#endif
首次通话期间出现此类延迟的原因可能是什么?如何减少延迟?
答案 0 :(得分:0)
您的clEnqueueMapBuffer()
调用被阻止(CL_TRUE
参数的blocking_map
),这意味着只有在映射操作完成后,该调用才会返回。如果您的命令队列不是并发的,那么任何先前排队的异步命令(例如排队的内核)都需要在映射甚至开始之前完成。如果有这些较早的命令,则实际上是在测量它们的完成以及内存映射操作。为避免这种情况,请在开始时钟之前添加一个clFinish()
呼叫。 (调用clFinish()
可能效率更高, not ,所以我建议您仅将其留作测量之用。)