GPU 编程的推动力

计算科学 并行计算 宠物 显卡 库达
2021-11-30 04:10:05

我对 GPGPU 编程陌生,所以如果这个问题不是特别合适,请原谅我。据我了解,与通常的 CPU 编程相比,GPU 编程是一项非常复杂的工程工作。必须非常小心分歧问题、平铺、固定内存分配和主机-设备通信/设备计算重叠。

在做了一些研究之后,我发现了似乎试图模仿 C++ STL的推力库。这是相当不错的。然而,基于我非常有限的经验,并且看到了获得良好性能所需的所有微观管理,我对性能有点怀疑。推力可以在内部有效地处理所有复杂的编程部分吗?一些非常知名的库,例如 PETSc,似乎使用了这个包,这让我相信它应该以某种方式使用。

我想知道与低级 CUDA 编程相比,在 CUDA 和推力方面有更多经验的人是否可以就软件包的性能说一两句话。我什么时候可以使用推力,什么时候应该切换回 CUDA?

3个回答

我在链接集群扩展项目中使用了 Thrust。根据具体情况,Thrust 的性能可以与您自己推出的低级实现一样好或更好(特别是reduce内核对我来说工作得很好)。然而,Thrust 的通用性和灵活性意味着它有时必须进行大量额外的复制、数组填充等,这可能会在一些令人讨厌的边缘情况下减慢它的速度。上次我使用sort它与 b40c 或 mgpu 等其他库相比非常慢。但是,NVIDIA 一直在努力提高 Thrust 的算法性能,以便将来可能不会成为问题。

您应该尝试使用 Thrust 和 CUDA 编写代码,然后使用 Visual Profiler 确定哪个更适合您感兴趣的特定任务。如果内存传输可能会占用您程序的大部分运行时间而您不这样做不想担心针对银行冲突、指令计数等优化自己的内核,那么我会使用 Thrust。它还有一个额外的好处,就是让你的代码更简洁,更容易让不熟悉 GPU 编程的人阅读。

推力(与大多数模板库一样)的目的是提供高级抽象,同时保持良好甚至出色的性能。

我建议不要太担心性能,而是问问自己是否

  • 您的应用程序可以根据在推力中实现的算法来描述,如果

  • 您喜欢编写“通用”并行代码的可能性,而无需深入寻找到给定硬件/软件架构的有效映射的血腥细节。

如果您对这两个问题都做出了积极回应,那么您应该能够以相对于仅 CUDA 实施而言更少的努力来实施您的程序。然后,您可以分析您的应用程序并决定是否值得尝试提高性能。

这就是说,我不得不承认我不喜欢“泛型”编程,因为我愿意在编写程序时学习新的东西。我会遵循另一条路线:在 python+numpy+scipy 中编写原型实现,然后为那些真正需要优化且适合在 GPU 上运行的 1%--2% 的代码添加 CUDA 内核。当然,这样做您需要某种先验知识,因为在原型设计阶段的错误决定(例如,不适合 CUDA 内核的数据结构)可能会对性能产生可怕的影响。通常需要更多的迭代才能获得好的代码,并且不能保证做得比推力更好。

我对推力没有个人经验,但我确实使用了 ViennaCL,这是另一个隐藏几乎所有细节的高级 GPU 库。从我自己的个人基准测试中,如果您忽略在内存中移动所需的时间,我可以看到实际计算速度提高了 2 倍至 40 倍。

什么时候应该使用 CPU 与推力与 CUDA 完全取决于您要解决的问题、您的技能以及可用的时间。我建议从解决所有 3 种方法的简单问题开始,看看它们的相对性能。然后您可以快速编写实际软件,对其进行基准测试,并在需要加速的区域应用适当的 gpu 方法,而不是浪费时间编写只会获得几分钟执行时间的 CUDA 软件.