3

我正在编写一个 CUDA 内核,其中涉及计算给定矩阵的最大值,并且我正在评估可能性。我能找到的最好方法是:

强制每个线程在共享内存中存储一​​个值,然后使用缩减算法来确定最大值(优点:最小分歧缺点:共享内存在 2.0 设备上限制为 48Kb)

我无法使用原子操作,因为同时存在读取和写入操作,因此同步线程无法同步线程。

你有什么其他想法吗?

4

7 回答 7

6

您可能还想使用带有 CUDA Thrust 的缩减例程,它是 CUDA 4.0 的一部分或在此处可用。

该库由一对 nVidia 工程师编写,与经过大量手工优化的代码相比毫不逊色。我相信还有一些网格/块大小的自动调整正在进行。

您可以通过包装原始设备指针轻松地与您自己的内核交互。

这是严格从快速集成的角度来看的。有关理论,请参阅 tkerwin 的答案。

于 2011-05-09T12:40:49.213 回答
5

这是减少 CUDA 的常用方法

在每个区块内,

1) 在每个线程的共享内存中保持一个运行减少的值。因此,每个线程将读取 n(我个人喜欢在 16 到 32 之间)、全局内存中的值并从这些值中更新减少的值

2) 在块内执行归约算法以获得每个区块的最终归约值。

这样,您将不需要比 (线程数) * sizeof (datatye) 字节更多的共享内存。

由于每个块都有一个缩减值,因此您需要执行第二次缩减传递才能获得最终值。

例如,如果每个块启动 256 个线程,并且每个线程读取 16 个值,那么每个块将能够减少 (256 * 16 = 4096) 个元素。

因此,给定 100 万个元素,您将需要在第一遍中启动大约 250 个块,而在第二遍中只需要一个块。

对于此配置的元素数量 > (4096)^2 的情况,您可能需要第三次通过。

您必须注意合并全局内存读取。您无法合并全局内存写入,但这是您需要承担的一项性能损失。

于 2011-05-07T23:04:37.167 回答
4

NVIDIA 有一个 CUDA 演示,可以减少:这里。随附的白皮书解释了设计背后的一些动机。

于 2011-05-07T22:05:47.343 回答
2

我发现这篇文档对于学习使用 CUDA 进行并行归约的基础知识非常有用。它有点老了,所以必须有额外的技巧来进一步提高性能。

于 2012-08-20T17:37:29.190 回答
1

实际上,您描述的问题实际上与矩阵无关。输入数据的二维视图并不重要(假设矩阵数据在内存中连续布局)。它只是对一系列值的缩减,所有矩阵元素都以它们在内存中出现的顺序排列。

假设矩阵表示在内存中是连续的,您只想执行简单的归约。而目前最好的实现——据我所知——是 nVIDIA 的 Duane Merill 的优秀libcub是有关其设备范围的最大值计算功能的文档。

但是请注意,除非矩阵很小,否则对于大多数计算来说,它只是线程读取数据并更新它们自己的线程特定最大值。只有当一个线程完成了对矩阵的大样本(或者更确切地说,一个大的跨步幅)的读取时,它才会将其局部最大值写入任何地方 - 通常写入共享内存以进行块级减少。至于原子,您可能会在atomicMax()每次读取大量矩阵元素时进行一次调用 - 如果不是更多,数以万计。

于 2016-10-22T09:58:51.050 回答
0

也可以使用该atomicAdd功能,但它的效率远低于上述方法。http://supercomputingblog.com/cuda/cuda-tutorial-4-atomic-operations/

于 2011-09-18T18:29:22.563 回答
0

如果你有 K20 或 Titan,我建议动态并行:午餐单线程内核,午餐 #items 工作内核线程以产生数据,然后午餐 #items/first-round-reduction-factor 线程进行第一轮减少,并继续午餐直到结果出来。

于 2013-05-02T20:58:36.240 回答