OpenCL并行化成本

OpenCL并行化成本,opencl,gpgpu,gpu,Opencl,Gpgpu,Gpu,我为OpenCL搭建了一个飞思卡尔I.MX6.Q平台,我得到了一些有趣的结果,我无法完全解释。我的算法是通过执行4个内核完成的,最后一个内核是我感兴趣的:一个经典的图像差异 我测试了两个版本,一个矢量化版本和一个经典版本(没有矢量化)。起初,我对并行化的结果感到惊讶:在这个平台上,必须选择OpenCL,只有要处理的图像包含超过180kpix(在算法中,图像作为缓冲区处理) 然而,对于这两种OpenCL实现,在开始时(对于小图像)都有常量执行时间(大约5毫秒)。我检查了一个空内核的执行时间,在这个

我为OpenCL搭建了一个飞思卡尔I.MX6.Q平台,我得到了一些有趣的结果,我无法完全解释。我的算法是通过执行4个内核完成的,最后一个内核是我感兴趣的:一个经典的图像差异

我测试了两个版本,一个矢量化版本和一个经典版本(没有矢量化)。起初,我对并行化的结果感到惊讶:在这个平台上,必须选择OpenCL,只有要处理的图像包含超过180kpix(在算法中,图像作为缓冲区处理)

然而,对于这两种OpenCL实现,在开始时(对于小图像)都有常量执行时间(大约5毫秒)。我检查了一个空内核的执行时间,在这个平台上,任何测试的映像(从32x32到1920x1024)的执行时间都在5ms左右

我将空内核的这些时间视为OpenCL差异的并行化成本,我想知道这个成本包含什么

我的内核编译是在工作台之外完成的,我不知道哪一步需要5毫秒。GPU处理的只是NDRange解释吗

如果有人对此有解释,我接受

巴蒂斯特

编辑:

我的时间测量和内核启动:

start_time = time_now();

cl_mem_flags mem_device_host;
if (device.getInfo<CL_DEVICE_HOST_UNIFIED_MEMORY>()==CL_TRUE)
    mem_device_host = CL_MEM_USE_HOST_PTR;
else
    mem_device_host = CL_MEM_COPY_HOST_PTR;

cl_status = kernel.setArg(0, input_image);
oclReturnOnError(cl_status, "Passage de l'argument 0 du kernel 'morph'")

cl_status = kernel.setArg(1, output_image);
oclReturnOnError(cl_status, "Passage de l'argument 1 du kernel 'morph'")

cl_status = kernel.setArg(2, input_SE);
oclReturnOnError(cl_status, "Passage de l'argument 2 du kernel 'morph'")

cl::Event eventMorph;
cl_status = commandQueue.enqueueNDRangeKernel(kernel,
    cl::NullRange,
    global_range,
    local_range
    NULL , &eventMorph);
oclReturnOnError(cl_status, "Ajout du kernel 'morph' à la queue de commande")

cl_status = eventMorph.wait();
oclReturnOnError(cl_status, "Attende d'exécution du kernel 'morph'")

end_time = time_now();
start_time=time_now();
cl_mem_标志mem_设备_主机;
if(device.getInfo()==CL\u TRUE)
mem_device_host=CL_mem_USE_host_PTR;
其他的
mem_device_host=CL_mem_COPY_host_PTR;
cl_status=kernel.setArg(0,输入_图像);
oclReturnOnError(cl_状态,“内核‘变形’参数0的通道”)
cl_status=kernel.setArg(1,输出_图像);
oclReturnOnError(cl_状态,“内核‘变形’参数1的通道”)
cl_status=kernel.setArg(2,输入_SE);
oclReturnOnError(cl_状态,“内核‘变形’参数2的通道”)
cl::eventMorph事件;
cl_status=commandQueue.enqueueNDRangeKernel(内核,
cl::零范围,
全球范围,
本地范围
NULL,&eventmorp);
oclReturnOnError(cl_状态,“内核‘变形’队列命令”)
cl_status=eventmorp.wait();
oclReturnOnError(cl_状态,“参与内核‘变形’的执行”)
结束时间=现在的时间();

您的问题主要是如何测量内核执行。使用操作系统time_now()会给您带来较差的分辨率,并且不是测试OpenCL性能的方法

此外,主机处理GPU工作负载的速度较慢。因此,如果您排队,不要强制执行(使用
clFlush()
),然后被动地等待完成,结果是感知性能非常差。由于您必须等待所有队列和提交,因此您将看到在调用和实际执行之间存在大量开销

run+wait模型对示例和演示有效,但不应用于实际系统或性能度量

测量性能的正确方法是使用
事件。您可以使用
cl::Event.getProfilingInfo()
cl::Event.getProfilingInfo()
来测量内核的开始和结束时间


运行系统的正确方法是仅在需要提取数据时强制执行阻塞调用(通常在
EnqueueReadBuffer()
)。这样,如果您将一系列内核排队,它们将一个接一个地运行,其间几乎没有空闲时间。

您能提供一些启动/测量代码吗?因为5ms,这是一个非常高的值。例如,在我的设置中,我有大约1U的执行开销。我测量内核执行和参数设置。对于我的空内核,我只有1个参数和几个编译选项,以使内核接近我的差异。但是我的设置有点差,我想(CPU 4核@1GHz,GPU 64核@500MHz)没有本地内存。我知道用事件来测量GPU时间执行的方法。但是如果我没有相同的时间度量参考(我比较C实现和OpenCL实现),这不是一个问题吗?无论如何,我都会试试看,看看有什么不同。