【问题标题】:OpenCL Parallelization CostOpenCL 并行化成本
【发布时间】:2013-12-13 08:34:26
【问题描述】:

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

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

但是对于两个 OpenCL 实现,在开始时(对于小图像)都有恒定的执行时间(大约 5 毫秒)。我检查了空内核的执行时间,对于任何测试的图像(从 32x32 到 1920x1024),它们在这个平台上总是大约 5 毫秒。

我将空内核的这些时间视为 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();

【问题讨论】:

  • 你能提供一些发射/测量的代码吗?由于 5ms,这是一个非常高的值。例如,在我的设置中,我有 1us 的执行开销。
  • 我添加一个例子。我测量内核执行和参数设置。对于我的空内核,我只有 1 个参数和几个编译选项来让内核接近我的差异。但我认为我的设置有点差(CPU 4 核 @ 1GHz 和 GPU 64 核在 4 CU @ 500MHz)没有本地内存

标签: opencl gpgpu gpu


【解决方案1】:

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

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

该运行+等待模型适用于示例和演示,但不应用于实际系统或性能测量。

衡量性能的正确方法是使用event。您可以使用cl::Event.getProfilingInfo&lt;CL_PROFILING_COMMAND_START&gt;()cl::Event.getProfilingInfo&lt;CL_PROFILING_COMMAND_END&gt;() 来测量内核的开始和结束时间。

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

【讨论】:

  • 是的,我知道用事件来测量 GPU 时间执行的方法。但是,如果我没有相同的时间测量参考(我将 C 实现与 OpenCL 进行比较),这不是问题吗?无论如何我都会尝试看看有什么不同。
猜你喜欢
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 2019-01-12
  • 1970-01-01
  • 1970-01-01
  • 2016-05-06
  • 2012-05-11
  • 2019-01-16
相关资源
最近更新 更多