Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image processing 如何确定我可以安全地传递到OpenCL内核/从OpenCL内核传递的图像的最大大小?_Image Processing_Opencl_D - Fatal编程技术网

Image processing 如何确定我可以安全地传递到OpenCL内核/从OpenCL内核传递的图像的最大大小?

Image processing 如何确定我可以安全地传递到OpenCL内核/从OpenCL内核传递的图像的最大大小?,image-processing,opencl,d,Image Processing,Opencl,D,我正在开发一个处理大型图像的OpenCL1.2应用程序。 目前,我正在测试的图像是16507x21244像素。我的内核在一个循环中运行,该循环对图像块进行操作。内核接收32bpp(rgba)的图像块,并输出4个像素块 让我们定义(正方形)块的一侧(以像素为单位)为块大小。也就是说,8192x8192像素正方形的块大小为8192。当然,如果图像不能很好地被块大小整除,则在右侧和底部有较小的矩形块。我的代码可以处理这个问题,但是在本文的其余部分,为了简单起见,让我们忽略这个问题 我正在尝试确定循环每

我正在开发一个处理大型图像的OpenCL1.2应用程序。 目前,我正在测试的图像是16507x21244像素。我的内核在一个循环中运行,该循环对图像块进行操作。内核接收32bpp(rgba)的图像块,并输出4个像素块

让我们定义(正方形)块的一侧(以像素为单位)为块大小。也就是说,8192x8192像素正方形的块大小为8192。当然,如果图像不能很好地被块大小整除,则在右侧和底部有较小的矩形块。我的代码可以处理这个问题,但是在本文的其余部分,为了简单起见,让我们忽略这个问题

我正在尝试确定循环每次迭代中可以操作的最大块大小,以及最佳块大小(可能不是最大块大小)

供参考。使用英伟达平台,使用Linux专有驱动程序,在<代码> GeFund GTX 560 TI/COD>中运行内核。

我最初天真的假设是我可以操作最大2d图像大小。 但是,这会导致
clenqueendrangekernel
返回错误代码-4(
CL\u MEM\u OBJECT\u ALLOCATION\u FAILURE

想想看,这对我来说很有意义。有了1Gib的视频内存,人们希望能够保存单个16384x16384像素纹理(32bpp)或8192x8192像素纹理(float4)。如果内核运行时两者都需要缓存在卡上,我们可以使用以下内存量:

   4 bytes-per-pixel * chunk size^2 (input image) 
+ 16 bytes-per-pixel * chunk size^2 (output image) 
= 1 GiB total video memory
求解我们得到的块大小

chunk size = sqrt(1GiB/20)
插入OpenCL报告的内存量(略小于1GiB-1023 MiB)并对结果进行铺垫,我们得到:

floor(sqrt(1072889856/20)) = 7324
但是,块大小为7324仍然会导致
CL\u MEM\u OBJECT\u ALLOCATION\u失败

我的下一个猜测是,我们无法传递大于最大分配大小的图像,OpenCL报告我的卡为268222464字节。因为我的输出图像有更大的像素宽度,它将决定我的区块大小

floor(sqrt(268222464/16)) = 4094
嘿,这真的管用现在,如果我们尝试扩大规模,会怎么样?令我惊讶的是,它没有失败。通过反复试验,我将6784缩小为实际的最大块大小。在6785,它开始抱怨
CL\u MEM\u OBJECT\u ALLOCATION\u FAILURE
。我不知道为什么最大值看起来是6784,我也不知道这是否是可重复的,或者该值是否波动(例如,视频内存中存在的其他状态会影响其可容纳的大小)。我还发现,使用块大小6784运行比使用基于最大分配的大小运行要慢几秒钟。我想知道这是否是因为OpenCL需要在后台执行多个(昂贵的)分配?我还注意到OpenCL能够报告的“内核参数的最大大小”(
CL\u DEVICE\u max\u PARAMETER\u size
)。然而,这个值似乎是假的。如果我只能传入4096个字节,那将把我限制为16x16像素

所以我只剩下两个基本问题:

  • 如何确定绝对最大块大小?
  • 如何确定最快的块大小?(除了试错法,还有其他方法吗?
  • 作为一个额外的问题,对于未来有关低级OpenCL硬件交互的此类问题,我是否可以求助于好的资源?

    最后,我将提供一些代码片段供同行评审;如果有任何建设性的批评,我将不胜感激


    一如既往,提前感谢您的帮助

    要回答您的直接问题:

    1)要确定单个内核操作可以使用的绝对最大块大小,必须知道“块大小”指的是什么。例如,OpenCL内存结构中有五个已定义的内存模型。其中之一是主机内存,我们将忽略它。另外四个是全局的、固定的、局部的和私有的

    要获得关于硬件支持的任何信息,我强烈建议访问底部记录的Khronos API文档。您可以收集大量有关设备的元数据。例如,存在设备可以支持的二维和/或三维图像的最大高度和最大宽度查询。我还建议查看CL_设备\本地\内存\大小和CL_设备\最大\计算\单位,以定义您的工作组。甚至还有一个CL_DEVICE_MAX_MEM_ALLOC_SIZE查询是允许的

    指出您对性能的担忧是,为您提供的用于处理的内存大小是工作组或项目的最佳最大大小(取决于查询)。可能发生的是内存溢出到全球空间。这需要在不同的工作线程之间分配更多内存,从而导致性能下降。对于该语句不是100%确定的,但是当您超过推荐的缓冲区大小时,这很可能是问题的一部分

    2)确定最快的块大小不需要尝试和错误。在Addison Wesley出版的《OpenCL编程指南》一书中,有一节介绍了如何在宿主应用程序中使用事件进行评测。允许对函数集进行分析。这些功能如下:

    • clEnqueue{Read | Write | Map}缓冲区
    • clEnqueue{Read | Write}BufferRect
    • 克伦奎{Read | Write | Map}图像
    • clEnqueueUnmapMemObject
    • clEnqueueCopyBuffer
    • clEnqueueCopyBufferRect
    • 克伦奎科皮影
    • 克伦奎科皮约特布弗
    • clEnqueueCopyBufferToImage
    • 克伦奎恩德兰奇核
    • 克伦奎茨克
    • 克伦奎恩蒂维克内尔