【问题标题】:A couple of CUDA-performance questions几个 CUDA 性能问题
【发布时间】:2012-10-15 03:59:30
【问题描述】:

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

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

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

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

  • 或者,是因为我在代码中有一个 if 语句吗?问题是,我只考虑和计算短距离,所以我有一个类似的声明(如果 dist

一百万谢谢! 斌

【问题讨论】:

  • 与前几代不同,Fermi 有一个自动缓存。您在 GPU 101 中学到的许多简单技巧都已过时。
  • 消除分支的一个小技巧是:count += (distance
  • @Nathan:GPU 支持一种称为预测的系统。它允许 GPU 根据某些条件“预测”机器代码指令的执行。编译器使用它来避免在主体中仅包含几条指令的条件分支。
  • @misha 谢谢!您是否认为 Fermi 的自动缓存可能涵盖了引入共享内存的潜在好处是可以理解的?
  • @Nathan 非常感谢!棘手的部分是我需要使用一个数组来跟踪一堆计数器,而且只有一小部分距离具有 dist

标签: performance parallel-processing cuda


【解决方案1】:

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

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

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

您正在处理的问题听起来像是著名的 n 体问题, 见Fast N-Body Simulation with CUDA

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 再次感谢罗杰! 1 & 3. 很清楚。但是你能详细说明你提到的管道和warp之间的关系吗?据我了解,每个扭曲,假设包含 32 个线程,“一起”执行相同的指令。他们真的在形成管道吗?
    • 2.所以我猜这里的缓存和上面提到的 Misha 一样,“Fermi 有一个自动缓存。你在 GPU 101 中学到的许多简单技巧都已经过时了。”?
    • @bin:当处理开始于 warp 中的一条指令时,该指令(具有不同的操作数)被发送到 32 个内核。然后在操作通过 32 个核心中的管道时,整个经线被暂停。某些类型的指令需要加载/存储和特殊功能单元。这些单元中的每一个都没有 32 个,因此对于这些单元,warp 会被调度多次,直到它的所有线程都得到服务。
    • @RogerDahl 调度程序将选择一个 warp 并发出 1 或 2 条指令(仅 CC 2.1 及更高版本支持 2 条指令)。流水线将读取寄存器和任何常量并将指令分派到数据路径(执行单元)。如果执行单元的宽度不足以容纳 32 个线程,那么它将在多个周期内发出。对于每种指令类型和每种体系结构,指令退出之前所花费的周期数是不同的。如果 warp 没有停止(例如数据或执行依赖),那么调度可以在下一个周期在同一个 warp 上发出另一条指令。
    • @RogerDahl 可以在 SM 上分配的线程数取决于占用率和设备限制。最大范围从 CC
    猜你喜欢
    • 2011-07-11
    • 2016-05-22
    • 2013-04-07
    • 2013-06-08
    • 1970-01-01
    • 2013-10-21
    • 2013-01-25
    • 1970-01-01
    • 2015-10-09
    相关资源
    最近更新 更多