在我的工作负载上运行 Intel VTune 时,我看到以下内容:
Memory Bound 50.8%
我阅读了英特尔文档,上面写着(英特尔文档):
Memory Bound 测量一小部分插槽,其中流水线可能由于需求加载或存储指令而停止。这主要是由于不完整的动态内存需求负载与执行饥饿相吻合,以及存储可能暗示管道背压的不太常见的情况。
这是否意味着我的应用程序中大约有一半的指令在等待内存时停滞了,还是比这更微妙?
在我的工作负载上运行 Intel VTune 时,我看到以下内容:
Memory Bound 50.8%
我阅读了英特尔文档,上面写着(英特尔文档):
Memory Bound 测量一小部分插槽,其中流水线可能由于需求加载或存储指令而停止。这主要是由于不完整的动态内存需求负载与执行饥饿相吻合,以及存储可能暗示管道背压的不太常见的情况。
这是否意味着我的应用程序中大约有一半的指令在等待内存时停滞了,还是比这更微妙?
VTune 使用的流水线槽概念解释如下:https ://software.intel.com/en-us/top-down-microarchitecture-analysis-method-win. 简而言之,pipeline slot 代表处理一个 uOp 所需的硬件资源。因此,对于 4 宽 CPU(大多数 Intel 处理器),我们每个周期可以执行 4 个 Ops,并且插槽总数将由 VTune 测量为 4 * CPU_CLK_UNHALTED.THREAD。Memory Bound 指标建立在 CYCLE_ACTIVITY.STALLS_MEM_ANY 事件上,该事件会导致您因内存而直接停顿。考虑到乱序。基本上只有当 CPU 停止并且同时它有运行中的负载时,计数器才会增加。如果有负载在进行中但 CPU 一直很忙,则不会将其视为内存停顿。因此,Memory Bound 指标可以非常准确地估计工作负载受内存性能问题的限制。50% 的值意味着一半的时间浪费在等待内存中的数据上。
插槽是管道的执行端口。一般来说,在 VTune 文档中,停顿可能意味着“未退役”或“未调度执行”。在这种情况下,它指的是发送零微指令的周期数。
根据VTune的include配置文件,Memory Bound
计算如下:
Memory_Bound
= Memory_Bound_Fraction
*BackendBound
Memory_Bound_Fraction
基本上是文档中提到的插槽的一部分。但是,根据优化手册中讨论的自顶向下方法,内存绑定度量是相对于后端绑定度量的。所以这就是它乘以 的原因BackendBound
。
我将专注于公式的第一项,Memory_Bound_Fraction
。第二项 的公式BackendBound
实际上很复杂。
Memory_Bound_Fraction
计算如下:
Memory_Bound_Fraction
= ( CYCLE_ACTIVITY.STALLS_MEM_ANY
+ RESOURCE_STALLS.SB
) * NUM_OF_PORTS
/ Backend_Bound_Cycles
*NUM_OF_PORTS
NUM_OF_PORTS
是目标 CPU 的微架构的执行端口数。这可以简化为:
Memory_Bound_Fraction
= CYCLE_ACTIVITY.STALLS_MEM_ANY
+ RESOURCE_STALLS.SB
/Backend_Bound_Cycles
CYCLE_ACTIVITY.STALLS_MEM_ANY
并且RESOURCE_STALLS.SB
是表演事件。Backend_Bound_Cycles
计算如下:
Backend_Bound_Cycles
= CYCLE_ACTIVITY.STALLS_TOTAL
+ UOPS_EXECUTED.CYCLES_GE_1_UOP_EXEC
- Few_Uops_Executed_Threshold
- Frontend_RS_Empty_Cycles
+RESOURCE_STALLS.SB
Few_Uops_Executed_Threshold
要么取决于其他指标,UOPS_EXECUTED.CYCLES_GE_2_UOP_EXEC
要么UOPS_EXECUTED.CYCLES_GE_3_UOP_EXEC
取决于其他指标。取决于某些指标,Frontend_RS_Empty_Cycles
要么是要么为零。RS_EVENTS.EMPTY_CYCLES
我意识到这个答案仍然需要很多额外的解释并且BackendBound
需要扩展。但是这个早期的编辑使答案准确。