小编mio*_*ura的帖子

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

我正在开发一个处理大图像的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
Run Code Online (Sandbox Code Playgroud)

解决我们得到的块大小

chunk size = sqrt(1GiB/20)
Run Code Online (Sandbox Code Playgroud)

插入OpenCL报告的内存量(略小于1GiB - 1023 MiB)并对结果进行分层,我们得到:

floor(sqrt(1072889856/20)) = 7324
Run Code Online (Sandbox Code Playgroud)

但是,仍然会产生7324的块大小CL_MEM_OBJECT_ALLOCATION_FAILURE.

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

floor(sqrt(268222464/16)) = 4094
Run Code Online (Sandbox Code Playgroud)

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

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

d image-processing opencl

11
推荐指数
1
解决办法
902
查看次数

相当于D中的remove_if

最近我对D编程语言感兴趣.我刚刚开始学习它,并且来自C++背景.我想知道是否有相当于std :: remove_if.我只看到删除浏览dlang网站上的文档.
如果没有直接的等价物,那么在D中获得相同结果的正确或最恰当的方法是什么?
编辑:我应该补充一点,我在擦除 - 删除的上下文中思考

c++ algorithm idioms d phobos

8
推荐指数
1
解决办法
184
查看次数

使用C++中的显式原型返回类型推导

我一直在玩g ++支持的返回类型演绎与-std = c ++ 1y.
如果您使用显式返回类型对函数进行原型化,然后尝试使用返回类型推导来定义函数,则编译器会抱怨一个模糊的旧声明:

std::string some_function();
...  
auto some_function(){ return std::string{"FOO"}; } //fails to compile
Run Code Online (Sandbox Code Playgroud)

有什么理由不适用吗?
我在定义中使用返回类型推导的基本原理是保持代码干净,但是为了自我记录的原因需要原型中的显式类型.关于何时何时不使用退货类型扣除的最佳做法的建议将不胜感激:)

为了更清楚,我想回答:
1.这是编译器中的实现错误吗?(我很确定不是这样)
2.这种类型的扣除是否可以完成,但提案不允许这样做?如果是这样,为什么不呢?
3.如果这是非常模糊的,那么推断类型并尝试将其与明确的前向声明相匹配的一些例子会让你遇到麻烦吗?
4.这背后是否有更深层次的实施具体问题?
这只是一种疏忽吗?

c++ return-type forward-declaration c++14

8
推荐指数
1
解决办法
571
查看次数

编译器如何将函数消除应用于不纯函数?

通常在编写代码时,我发现自己多次使用来自特定函数调用的值.我意识到明显的优化是在变量中捕获这些重复使用的值.这个(伪代码):

function add1(foo){ foo + 1; }
...
do_something(foo(1));
do_something_else(foo(1));
Run Code Online (Sandbox Code Playgroud)

变为:

function add1(foo){ foo + 1; }
...
bar = foo(1);
do_something(bar);
do_something_else(bar);
Run Code Online (Sandbox Code Playgroud)

但是,根据我的经验,这样做明确地使代码的可读性降低.如果我们选择的语言允许函数产生副作用,我认为编译器无法进行这种优化.

最近我调查了这个,如果我理解正确的话,这个优化是/可以用于函数必须纯粹的语言.这并不让我感到惊讶,但据说这也可以用于不纯的功能.通过一些快速的谷歌搜索,我发现了这些片段: GCC 4.7 Fortran改进

执行前端优化时,-faggressive-function-elimination选项允许删除重复的函数调用,即使对于不纯的函数也是如此.

编译器优化(维基百科)

例如,在某些语言中,不允许函数产生副作用.因此,如果程序使用相同的参数对同一函数进行多次调用,则编译器可以立即推断函数的结果只需要计算一次.在允许函数具有副作用的语言中,可以采用另一种策略.优化器可以确定哪个函数没有副作用,并将此类优化限制为无副作用函数.只有在优化程序可以访问被调用函数时,才能进行此优化.

根据我的理解,这意味着优化器可以确定函数何时是纯的,并在函数执行时执行此优化.我这样说是因为如果一个函数在给定相同的输入时总是产生相同的输出,并且没有副作用,那么它将满足两个条件被认为是纯粹的.

这两个片段为我提出了两个问题.

  1. 如果函数不纯,编译器如何能够安全地进行优化?(作为in -faggressive-functional-elimination)
  2. 编译器如何确定函数是否纯粹?(如维基百科文章中提出的策略)

最后:

  • 这种优化是否可以应用于任何语言,或仅在满足某些条件时?
  • 即使对于非常简单的功能,这种优化是否也是值得的?
  • 存储和检索堆栈中的值会产生多少开销?

如果这些是愚蠢或不合逻辑的问题,我道歉.它们只是我最近一直很好奇的一些东西.:)

language-agnostic compiler-construction optimization function compiler-optimization

7
推荐指数
1
解决办法
362
查看次数