第一次clEnqueueMapBuffer调用需要很多时间

时间:2018-11-12 18:11:11

标签: c performance memory-management gpu opencl

我在采用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

首次通话期间出现此类延迟的原因可能是什么?如何减少延迟?

1 个答案:

答案 0 :(得分:0)

您的clEnqueueMapBuffer()调用被阻止(CL_TRUE参数的blocking_map),这意味着只有在映射操作完成后,该调用才会返回。如果您的命令队列不是并发的,那么任何先前排队的异步命令(例如排队的内核)都需要在映射甚至开始之前完成。如果有这些较早的命令,则实际上是在测量它们的完成以及内存映射操作。为避免这种情况,请在开始时钟之前添加一个clFinish()呼叫。 (调用clFinish()可能效率更高, not ,所以我建议您仅将其留作测量之用。)