【发布时间】:2019-04-15 12:10:49
【问题描述】:
我在 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
第一次通话时出现这种延迟的原因可能是什么?如何减少延迟?
【问题讨论】:
-
您确定在您调用
clEnqueueMapBuffer()之前,命令队列上的任何先前操作(例如排队内核)已经完成了吗?如果不确定,请尝试在映射前插入clFinish()。 (一般来说,clFinish()是不需要的,没有它可能会更快,但是如果没有它,异步排队的命令会导致误导时间测量。) -
另一种可能性是简单的实现是将数据从 GPU VRAM 复制到主机内存,这需要时间。在这种情况下,您可能希望尝试在缓冲区创建时删除
CL_MEM_ALLOC_HOST_PTR标志,和/或使用clEnqueueReadBuffer() 让GPU 的DMA 控制器执行复制。 (如果您只是使用 memcpy 将所有数据复制出来,那么使用映射 API 并没有多大意义 - 这样做的目的是允许直接的零复制访问。) -
你是对的。有未完成的操作。调用 clFinish() 需要所有时间:clFinish 148326 clEnqueueMapBuffer 155
-
酷,我已经发布了一个更详细地解释这一点的答案。希望一切都有意义!
标签: c performance memory-management gpu opencl