当前位置:  开发笔记 > 运维 > 正文

如何确定我可以安全地传入/传出OpenCL内核的图像的最大大小?

如何解决《如何确定我可以安全地传入/传出OpenCL内核的图像的最大大小?》经验,为你挑选了0个好方法。

我正在开发一个处理大图像的OpenCL 1.2应用程序.目前,我正在测试的图像是16507x21244像素.我的内核在一个循环中运行,该循环对图像块进行操作.内核需要32bpp(rgba)的图像块,并将float4像素块传递出去.

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

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

作为参考,这是我的机器上的clinfo实用程序报告的信息.我Geforce GTX 560 Ti使用他们专有的Linux驱动程序在Nvidia平台上运行我的内核.

我最初的天真假设是我可以操作最大2d图像大小.但是,这会导致clEnqueueNDRangeKernel返回-4(CL_MEM_OBJECT_ALLOCATION_FAILURE)的错误代码.

想一想,这对我来说很有意义.凭借1 GiB的视频内存,人们可以期望能够容纳单个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_MEM_OBJECT_ALLOCATION_FAILURE.

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

floor(sqrt(268222464/16)) = 4094

嘿,这确实有效!现在如果我们试图变大呢?令我惊讶的是,它并没有失败.通过反复试验,我将6784缩小为实际的最大块大小.在6785,它开始抱怨CL_MEM_OBJECT_ALLOCATION_FAILURE.我不知道为什么max似乎是6784,我不知道这是否可重复或者值是否波动(例如视频内存中存在的其他状态会影响它能保持多少.)我也发现运行时块大小为6784比基于最大分配的大小运行慢几秒.我想知道这是否是因为OpenCL需要在引擎盖下执行多个(昂贵的)分配?我还注意到OpenCL能够报告的"内核参数的最大大小"(CL_DEVICE_MAX_PARAMETER_SIZE).但是,这个价值似乎是假的.如果我只能传入4096个字节,那么我将限制为16x16像素!

所以我留下了两个基本问题:

    如何确定绝对最大块大小?

    如何确定最快的块大小?(除了试错之外还有其他方法吗?)

作为一个额外的问题,我是否有任何好的资源可以用于关于低级OpenCL硬件交互的这种性质的未来问题

最后,我将为同行评审提供一些代码片段; 我会非常感谢任何建设性的批评!

主机代码模块(dlang)

设置OpenCL程序的包装器(dlang)

内核代码

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

推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有