首页 > 解决方案 > 发布了重放的加载/存储指令

问题描述

关于加载/存储指令有两个nvprof指标,它们是ldst_executedldst_issued。我们知道executed<=issued。我希望那些发出但未执行的加载/存储与分支预测和其他不正确的预测有关。但是,从这个(幻灯片 9)文档和这个主题中,发出但未执行的指令与序列化和重放有关。

我不知道这个原因是否适用于加载/存储指令。此外,我想知道为什么这样的术语用于已发出但未执行的指令?如果出于某种原因存在序列化,则会多次执行指令。那么,为什么它们不被视为executed

对此有何解释?

标签: cudanvidianvprof

解决方案


NVIDIA 架构通过为一组称为 warp 的线程发出指令来优化内存吞吐量。如果每个线程访问一个连续的数据元素或相同的元素,那么访问可以非常有效地执行。但是,如果每个线程访问不同高速缓存行中的数据或同一存储库中不同地址的数据,则存在冲突并且必须重播指令。

inst_executed 是退出指令的计数。inst_issued 是发出的指令计数。在向量内存访问、内存地址冲突、内存库冲突等情况下,一条指令可能会被多次发布。在每次发布时,线程掩码都会减少,直到所有线程都完成。

区别有两个原因: 1. 指令的退出表示数据依赖关系的完成。尽管可能重播,但数据依赖性仅解决了 1 次。2.发出和执行之间的比率是显示节省warp调度程序发出周期机会的简单方法。

在 Fermi 和 Kepler SM 中,如果遇到内存冲突,则重播(重新发出)指令,直到所有线程完成。这是由 warp 调度程序执行的。这些回放消耗了发布周期,降低了 SM 向数学管道发布指令的能力。在此 SM 中,已发布 > 已执行表示优化的机会,尤其是在已发布 IPC 较高的情况下。

在用于向量访问的 Maxwell-Turing SM 重放中,地址冲突和内存冲突由内存单元(共享内存、L1 等)重放,并且不会窃取 warp 调度程序发出周期。在这个 SM 中发出的很少超过百分之几以上的执行。

示例:内核加载一个 32 位值。warp 中的所有 32 个线程都处于活动状态,每个线程访问一个唯一的缓存行(步长 = 128 字节)。

在 Kepler (CC3.*) SM 上,该指令发出 1 次,然后再重放 31 次,因为 Kepler L1 每个请求只能执行 1 个标签查找。

inst_executed = 1 inst_issued = 32

在 Kepler 上,对于 L1 中丢失的每个请求,必须再次重播该指令。如果 L1 缓存中的所有线程都未命中,则

inst_executed = 1 inst_issued >= 64 = 32 次请求 + 32 次未命中重播

在 Maxwell - Turing 架构上,回放由 SM 内存系统执行。重播可以限制内存吞吐量,但不会阻止 warp 调度程序向数学管道发出指令。

inst_executed = 1 inst_issued = 1

在 Maxwell-Turing 上,Nsight Compute/Perfworks 公开了每个内存管道的吞吐量计数器,包括由于内存库冲突、原子序列化、地址分歧等导致的周期数。


推荐阅读