高性能的 CUDA 前缀和/扫描函数,寻找替代 thrust、cuDPP 库

7
我正在寻找CUDA项目中用于高性能多行扫描/多前缀和(一次内核执行中的多行数据)的函数。我已经尝试了Thrust库中的一个功能,但速度太慢了。而且,在使用nvcc的调试标志(-g -G)编译后,Thrust会崩溃。在失败了Thrust之后,我关注了cuDPP库,它曾是CUDA工具包的一部分。cuDPP的性能非常好,但该库与最新的CUDA 5.5不兼容,并且在使用内存检查器进行调试时,cudppMultiScan()函数存在一些全局内存违规问题。(CUDA 5.5,nsight 3.1,Visual Studio 2010,GTX 260 cc 1.3)。有人知道除了这两个库以外还有什么可用吗?

你看过我们在AccelerEyes开发的ArrayFire吗? - arrayfire
不,我以前没有见过这个,看起来非常有趣!谢谢! :) 它的性能怎么样?它是更注重生产力还是性能的库? - user1946472
如果想要使用Thrust来扫描矩阵的行,请不要重复调用inclusive_scan。为每一行分配一个索引,并使用inclusive_scan_by_key。您可以参考此示例进行适应。 - Jared Hoberock
对于单个向量,arrayfire 在数千个元素时要么更好,要么与 thrust 相当(在数百万个元素时)。对于多个矩阵,arrayfire 只启动一个内核,因此比多次启动 thrust 更快。来源:我编写了这段代码。您可以通过我的个人资料上的电子邮件与我联系以获取更多信息。 - Pavan Yalamanchili
@JaredHoberock 针对一个内存绑定算法需要读取额外的向量并不理想。但是这比多次启动内核要好。 - Pavan Yalamanchili
2个回答

2
这些库,特别是thrust,尽可能地通用化,优化往往需要专门化:例如,算法的专门化可以使用共享内存来处理基本类型(如int或float),但通用版本则无法这样做。有时候在特定情况下会缺少专门化!
尽可能多地使用这些经过充分测试的通用库是个好主意,但有时候,在某些性能关键部分,你应该考虑自己实现。
在你的情况下,你希望为不同的行并行进行多次扫描。一个好的实现不会单独为不同的行运行扫描:它将具有相同的内核调用,同时运行所有行的所有元素。根据其索引,线程可以知道它正在处理哪一行,并忽略行外的所有数据。
这种专门化要求一个返回吸收值的函数对象,以防止混合行。尽管如此,你自己仔细的实现可能会更快。

2
要编写自己的前缀扫描,您可以参考以下内容:
  1. CUDA SDK中的扫描示例;
  2. N. Wilt的《CUDA手册》第13章;
  3. S. Cook的《CUDA编程,GPU并行计算开发者指南》第6章;
  4. 使用CUDA进行并行前缀和(扫描)
要进行多个前缀和,您可以多次启动相同的内核(如a.lasram建议的那样),或尝试通过CUDA流实现并发性,不过我不知道这是否能够有效地适用于您的卡。

使用流是一个很好的想法,但我认为更好的方法是启动一个单一的内核,其中每个线程将在一个选定的行中“夹紧”计算。 - a.lasram
我有231行1424个浮点数,因此在单独的内核中执行每一行会导致由cudalaunch引起的时间开销过大。cuDPP在我的机器上(gtx260)大约需要0.11毫秒完成这项工作,对我来说是非常优秀的结果!在性能方面,cuDPP库是完美的选择。目前,我将尝试@accelereyes建议的arrayFire库。感谢您的回答。 - user1946472

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接