繁体   English   中英

CUDA共享内存-内核的总和减少

[英]CUDA shared memory - sum reduction from kernel

我正在处理图像多维数据集(450x450x1500)的大型数据集。 我有一个可以处理单个数据元素的内核。 每个数据元素产生6个中间结果(浮点数)。 我的块包含1024个线程。 每个线程(6个浮点数组)将6个中间结果存储在共享内存中。 但是,现在我需要将每个中间结果相加,以产生一个总和(6个总和值)。 我没有足够的全局内存来将这6个float数组保存到全局内存,然后从推力或宿主代码中的任何其他库中进行缩减。

共享内存中的数组上是否可以从内核函数内部调用任何还原例程?

解决这个问题的最佳方法是什么? 我是CUDA编程的新手,欢迎任何建议。

这似乎不太可能:

我没有足够的全局内存来将这6个float数组保存到全局内存,然后从推力或宿主代码中的任何其他库中进行缩减。

我无法想象您将如何有足够的空间来将数据存储在共享内存中,而不是在全局内存中。

无论如何, CUB提供了减少例程,可以从线程块内调用该例程,并且可以对共享内存中存储的数据进行操作。

或者,您可以编写自己的总和减少代码。 这并不是很难做到的,因此有很多关于此的问题,例如这个

或者,您可以修改cuda示例代码

更新

看完所有评论后,我了解到,您无需进行450x450x6倍的缩减,而不是进行1或几次缩减。

在这种情况下,有一个更简单的解决方案。

您无需为每个1500-D向量实施相对复杂的并行归约。由于您已经有450x450x6个要归约的向量,因此可以使用传统的串行归约方法并行缩减所有这些向量。

您可以使用具有16x16线程的块来处理图像的特定区域,并使用具有29x29块的网格来覆盖整个450x450图像。

在每个线程中,您可以迭代1500个帧。 在每个迭代中,您可以先计算6个中间结果,然后将它们添加到总和中。 完成所有迭代后,您可以将6个和写入全局内存。

这样就完成了内核设计。 不需要共享的内存。

您会发现性能非常好。 由于这是内存绑定操作,因此它不会比只访问一次所有图像多维数据集数据长得多。

如果您没有足够的全局内存用于整个多维数据集,则可以将其分成[1500] [225] [225]的4个子多维数据集,然后在每个子多维数据集上调用内核例程。 您唯一需要更改的是网格大小。

看看是彻底解释了CUDA并行减少。

如果我正确理解,则每个线程应总结为“仅” 6浮点数。

我不确定一般通过并行减少这样做是否值得,因为您会获得性能上的提升。

如果您以开普勒为目标,那么如果正确设置块大小,以使中间结果以某种方式适合流多处理器的寄存器,则可以尝试使用随机播放操作。

正如罗伯特·克罗维拉(Robert Crovella)所指出的那样,您关于存储中间结果的可能性的陈述似乎很奇怪,因为全局内存的数量肯定大于共享内存的数量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM