3

这是我第一次在这里提问,所以提前非常感谢,请原谅我的无知。而且我刚刚开始进行 CUDA 编程。

基本上,我有一堆点,我想计算所有成对的距离。目前我的内核函数只保留一个点,并迭代地读取所有其他点(从全局内存),并进行计算。以下是我的一些困惑:

  • 我正在使用具有 448 个内核的 Tesla M2050。但是我当前的并行版本(内核<<<128,16,16>>>)实现了更高的并行度(比内核<<<1,1,1>>>快约600倍)。可能是由于多线程问题或管道问题,还是它们实际上表示同一件事?

  • 我想进一步提高性能。所以我想使用共享内存来为每个多处理块保存一些输入点。但新代码同样快。可能的原因是什么?这可能与我设置的线程过多有关吗?

  • 或者,是因为我在代码中有一个 if 语句吗?问题是,我只考虑和计算短距离,所以我有一个类似的声明(如果 dist < 200)。我应该为这个担心多少?

一百万谢谢!垃圾桶

4

2 回答 2

4

Mark Harris 有一个关于优化 CUDA 的非常好的演讲:Optimizing Parallel Reduction in CUDA

算法优化
寻址变化,算法级联
11.84 倍加速,结合!
代码优化
循环展开
2.54 倍加速,组合

有一个额外的操作语句确实会导致问题,尽管这将是您想要优化的最后一件事,如果不仅仅是因为您需要在实现大小假设之前知道代码的布局!

您正在处理的问题听起来像著名的 n 体问题,请参阅使用 CUDA 进行快速 N 体模拟

如果您可以避免进行成对计算,则可以实现额外的性能提升,例如,元素太远而无法相互影响。这适用于任何可以用几何表示的关系,无论是成对成本还是带有弹簧的物理模拟。我最喜欢的方法是将网格划分为盒子,每个元素通过划分将自己放入盒子中,然后只评估相邻盒子之间的成对关系。这可以称为 O(n*m)。

于 2012-10-25T03:31:53.323 回答
3

(1) GPU 并行运行的线程数比内核数多得多。这是因为每个核心都是流水线的。在计算能力 2.0 (Fermi) 架构上,操作大约需要 20 个周期。因此,对于每个时钟周期,核心开始执行一项新操作,返回一个操作的完成结果,并将所有其他(大约 18 个)操作向完成方向再移动一步。因此,要使 GPU 饱和,您可能需要 448 * 20 线程。

(2) 这可能是因为您的值被缓存在 L1 和 L2 缓存中。

(3) 这取决于你在if条件句中做了多少工作。GPU 必须通过其中的所有代码在一个扭曲中运行所有 32 个线程,if即使只有其中一个线程的条件为真。如果与内核的其余部分相比,条件代码中有很多代码,并且相对视图线程通过该代码路径,那么您最终可能会得到较低的计算吞吐量。

于 2012-10-25T03:19:57.000 回答