Intel 性能监视器计数器可以用于测量内存带宽吗?
Can the Intel performance monitor counters be used to measure memory bandwidth?
英特尔 PMU 能否用于测量每个内核 read/write 内存带宽使用情况?这里 "memory" 表示 DRAM(即不命中任何缓存级别)。
我不确定英特尔 PMU,但我认为您可以使用英特尔 VTune 放大器 (https://software.intel.com/en-us/intel-vtune-amplifier-xe)。这个有很多性能监控工具(内存,cpu缓存,cpu)。也许这对你有用。
是的,间接的。您可以使用计数器之间的关系(包括时间戳)来推断其他数字。例如,如果您以 1 秒为间隔进行采样,并且有 N 个最后一级 (3) 缓存未命中,您可以非常确定每秒占用 N*CacheLineSize 字节。
将它准确地与程序 activity 联系起来有点棘手,因为这些未命中可能反映了 cpu 预取、中断 activity 等
还有一个“这个cpu不算数(MMX,SSE,AVX,..)除非这个配置位处于这个状态”的问题;因此自己滚动很麻烦....
是的,这是可能的,尽管它不一定像对通常的 PMU 计数器进行编程那样简单。
一种方法是使用通过 PCI space 访问的可编程内存控制器计数器。一个好的起点是在 pcm-memory
at pcm-memory.cpp 中检查英特尔自己的实现。此应用程序向您显示每个套接字或每个内存控制器的吞吐量,适用于某些用途。特别是,带宽在所有内核之间共享,因此在安静的机器上,您可以假设大部分带宽与被测进程相关联,或者如果您想在套接字级别进行监控,这正是您想要的。
另一种方法是对 "offcore repsonse" 计数器进行仔细的编程。据我所知,这些与 L2(最后一个核心私有缓存)和系统其余部分之间的流量有关。您可以根据 offcore 响应的结果进行过滤,因此您可以使用各种 "L3 miss" 事件的组合并乘以缓存行大小以获得读写带宽。事件的粒度非常细,因此您可以首先根据导致访问的原因进一步分解:指令获取、数据需求请求、预取等。
offcore 响应计数器通常落后于 perf
和 likwid
等工具的支持,但至少最近的版本似乎有合理的支持,即使对于像 SKL 这样的客户端部分也是如此。
核外响应性能监控工具可用于计算 IDI 上来自特定核心的所有核心发起的 请求。请求类型字段可用于统计特定类型的请求,例如需求数据读取。但是,要测量每个内核的内存带宽,请求数必须以某种方式转换为每秒字节数。大多数请求都是缓存行大小,即 64 字节。其他请求的大小可能未知,并且可能会向内存带宽添加一些小于或大于缓存行大小的字节。这些包括高速缓存行拆分锁定请求、WC 请求、UC 请求和 I/O 请求(但这些不贡献内存带宽),以及需要完成所有待处理写入的 fence 请求(MFENCE
, SFENCE
, 和序列化指令).
如果您只对可缓存带宽感兴趣,那么您可以计算可缓存请求的数量并将其乘以 64 字节。这可能是非常准确的,假设可缓存的缓存行拆分锁定请求很少见。不幸的是,从 L3(或 L4,如果可用)到内存的写回不能由任何当前微体系结构上的核外响应工具计算。这样做的原因是这些写回不是核心发起的,通常是由于 L3 中的冲突未命中而发生的。因此,可以计算在 L3 中丢失并导致写回的请求,但 offcore 响应工具无法让您确定是否有任何对 L3(或 L4)的请求导致了写回。这就是为什么不可能计算回写到内存 "per core."
此外,offcore 响应事件需要一个可编程的性能计数器,它是 0、1、2 或 3 之一(但在禁用 hyptherhtreading 时不是 4-7)。
Intel Xeon Broadwell 支持许多 Resource Director Technology (RDT) 功能。特别是,它支持 Memory Bandwidth Monitoring (MBM),这是一般情况下准确测量每个内核内存带宽的唯一方法。
MBM 相对于非核心响应具有三个优势:
- 它使您能够测量用资源 ID 标识的一个或多个任务的带宽,而不仅仅是每个内核。
- 它不需要通用可编程性能计数器之一。
- 它可以准确测量本地或总带宽,包括回写到内存。
offcore response的优点是支持request type, supplier type, snoop info字段。
Linux支持kernel version 4.6开头的MBM。在 4.6 到 4.13 中,perf
支持使用以下事件名称的 MBM 事件:
intel_cqm_llc/local_bytes - bytes sent through local socket memory controller
intel_cqm_llc/total_bytes - total L3 external bytes sent
事件也可以通过编程方式访问。
从 4.14, the implementation of RDT in Linux has significantly changed 开始。
在我的 BDW-E5(双插槽)系统 运行 内核版本 4.16 上,我可以使用以下命令序列查看 MBM 的字节数:
// Mount the resctrl filesystem.
mount -t resctrl resctrl -o mba_MBps /sys/fs/resctrl
// Print the number of local bytes on the first socket.
cat /sys/fs/resctrl/mon_data/mon_L3_00/mbm_local_bytes
// Print the number of total bytes on the first socket.
cat /sys/fs/resctrl/mon_data/mon_L3_00/mbm_total_bytes
// Print the number of local bytes on the second socket.
cat /sys/fs/resctrl/mon_data/mon_L3_01/mbm_local_bytes
// Print the number of total bytes on the second socket.
cat /sys/fs/resctrl/mon_data/mon_L3_01/mbm_total_bytes
我的理解是,字节数是从系统复位后开始计算的。
注意,默认情况下,被监控的资源是整个socket。
不幸的是,包括 MBM 在内的大多数 RDT 特征结果是 buggy on Skylake processors that support it. According to SKZ4 and SKX4:
Intel® Resource Director Technology (RDT) Memory Bandwidth Monitoring
(MBM) does not count cacheable write-back traffic to local
memory. This results in the RDT MBM feature under counting total
bandwidth consumed.
这就是它disabled by default on Linux when running on Skylake-X and Skylake-SP (which are the only Skylake processors that support MBM). You can enable MBM by adding the following parameter rdt=mbmtotal,mbmlocal
到内核命令行的原因。某些寄存器中没有标志来启用或禁用 MBM 或任何其他 RDT 功能。相反,这是在内核中的某些数据结构中进行跟踪的。
在 Intel Core 2 微架构上,可以使用 BUS_TRANS_MEM
事件测量每个内核的内存带宽,如 here 所述。
在某些架构上,使用 perf
您可以访问内存控制器的非核心 PMU 计数器。
$ perf list
[...]
uncore_imc_0/cas_count_read/ [Kernel PMU event]
uncore_imc_0/cas_count_write/ [Kernel PMU event]
uncore_imc_0/clockticks/ [Kernel PMU event]
[...]
然后:
$ perf -e "uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/" <program> <arguments>
将报告从内存控制器#0 读取和写入操作时从主内存传输到高速缓存的字节数。将该数字除以所用时间,即可得出所用平均内存带宽的近似值。
英特尔 PMU 能否用于测量每个内核 read/write 内存带宽使用情况?这里 "memory" 表示 DRAM(即不命中任何缓存级别)。
我不确定英特尔 PMU,但我认为您可以使用英特尔 VTune 放大器 (https://software.intel.com/en-us/intel-vtune-amplifier-xe)。这个有很多性能监控工具(内存,cpu缓存,cpu)。也许这对你有用。
是的,间接的。您可以使用计数器之间的关系(包括时间戳)来推断其他数字。例如,如果您以 1 秒为间隔进行采样,并且有 N 个最后一级 (3) 缓存未命中,您可以非常确定每秒占用 N*CacheLineSize 字节。
将它准确地与程序 activity 联系起来有点棘手,因为这些未命中可能反映了 cpu 预取、中断 activity 等
还有一个“这个cpu不算数(MMX,SSE,AVX,..)除非这个配置位处于这个状态”的问题;因此自己滚动很麻烦....
是的,这是可能的,尽管它不一定像对通常的 PMU 计数器进行编程那样简单。
一种方法是使用通过 PCI space 访问的可编程内存控制器计数器。一个好的起点是在 pcm-memory
at pcm-memory.cpp 中检查英特尔自己的实现。此应用程序向您显示每个套接字或每个内存控制器的吞吐量,适用于某些用途。特别是,带宽在所有内核之间共享,因此在安静的机器上,您可以假设大部分带宽与被测进程相关联,或者如果您想在套接字级别进行监控,这正是您想要的。
另一种方法是对 "offcore repsonse" 计数器进行仔细的编程。据我所知,这些与 L2(最后一个核心私有缓存)和系统其余部分之间的流量有关。您可以根据 offcore 响应的结果进行过滤,因此您可以使用各种 "L3 miss" 事件的组合并乘以缓存行大小以获得读写带宽。事件的粒度非常细,因此您可以首先根据导致访问的原因进一步分解:指令获取、数据需求请求、预取等。
offcore 响应计数器通常落后于 perf
和 likwid
等工具的支持,但至少最近的版本似乎有合理的支持,即使对于像 SKL 这样的客户端部分也是如此。
核外响应性能监控工具可用于计算 IDI 上来自特定核心的所有核心发起的 请求。请求类型字段可用于统计特定类型的请求,例如需求数据读取。但是,要测量每个内核的内存带宽,请求数必须以某种方式转换为每秒字节数。大多数请求都是缓存行大小,即 64 字节。其他请求的大小可能未知,并且可能会向内存带宽添加一些小于或大于缓存行大小的字节。这些包括高速缓存行拆分锁定请求、WC 请求、UC 请求和 I/O 请求(但这些不贡献内存带宽),以及需要完成所有待处理写入的 fence 请求(MFENCE
, SFENCE
, 和序列化指令).
如果您只对可缓存带宽感兴趣,那么您可以计算可缓存请求的数量并将其乘以 64 字节。这可能是非常准确的,假设可缓存的缓存行拆分锁定请求很少见。不幸的是,从 L3(或 L4,如果可用)到内存的写回不能由任何当前微体系结构上的核外响应工具计算。这样做的原因是这些写回不是核心发起的,通常是由于 L3 中的冲突未命中而发生的。因此,可以计算在 L3 中丢失并导致写回的请求,但 offcore 响应工具无法让您确定是否有任何对 L3(或 L4)的请求导致了写回。这就是为什么不可能计算回写到内存 "per core."
此外,offcore 响应事件需要一个可编程的性能计数器,它是 0、1、2 或 3 之一(但在禁用 hyptherhtreading 时不是 4-7)。
Intel Xeon Broadwell 支持许多 Resource Director Technology (RDT) 功能。特别是,它支持 Memory Bandwidth Monitoring (MBM),这是一般情况下准确测量每个内核内存带宽的唯一方法。
MBM 相对于非核心响应具有三个优势:
- 它使您能够测量用资源 ID 标识的一个或多个任务的带宽,而不仅仅是每个内核。
- 它不需要通用可编程性能计数器之一。
- 它可以准确测量本地或总带宽,包括回写到内存。
offcore response的优点是支持request type, supplier type, snoop info字段。
Linux支持kernel version 4.6开头的MBM。在 4.6 到 4.13 中,perf
支持使用以下事件名称的 MBM 事件:
intel_cqm_llc/local_bytes - bytes sent through local socket memory controller
intel_cqm_llc/total_bytes - total L3 external bytes sent
事件也可以通过编程方式访问。
从 4.14, the implementation of RDT in Linux has significantly changed 开始。
在我的 BDW-E5(双插槽)系统 运行 内核版本 4.16 上,我可以使用以下命令序列查看 MBM 的字节数:
// Mount the resctrl filesystem.
mount -t resctrl resctrl -o mba_MBps /sys/fs/resctrl
// Print the number of local bytes on the first socket.
cat /sys/fs/resctrl/mon_data/mon_L3_00/mbm_local_bytes
// Print the number of total bytes on the first socket.
cat /sys/fs/resctrl/mon_data/mon_L3_00/mbm_total_bytes
// Print the number of local bytes on the second socket.
cat /sys/fs/resctrl/mon_data/mon_L3_01/mbm_local_bytes
// Print the number of total bytes on the second socket.
cat /sys/fs/resctrl/mon_data/mon_L3_01/mbm_total_bytes
我的理解是,字节数是从系统复位后开始计算的。
注意,默认情况下,被监控的资源是整个socket。
不幸的是,包括 MBM 在内的大多数 RDT 特征结果是 buggy on Skylake processors that support it. According to SKZ4 and SKX4:
Intel® Resource Director Technology (RDT) Memory Bandwidth Monitoring (MBM) does not count cacheable write-back traffic to local memory. This results in the RDT MBM feature under counting total bandwidth consumed.
这就是它disabled by default on Linux when running on Skylake-X and Skylake-SP (which are the only Skylake processors that support MBM). You can enable MBM by adding the following parameter rdt=mbmtotal,mbmlocal
到内核命令行的原因。某些寄存器中没有标志来启用或禁用 MBM 或任何其他 RDT 功能。相反,这是在内核中的某些数据结构中进行跟踪的。
在 Intel Core 2 微架构上,可以使用 BUS_TRANS_MEM
事件测量每个内核的内存带宽,如 here 所述。
在某些架构上,使用 perf
您可以访问内存控制器的非核心 PMU 计数器。
$ perf list
[...]
uncore_imc_0/cas_count_read/ [Kernel PMU event]
uncore_imc_0/cas_count_write/ [Kernel PMU event]
uncore_imc_0/clockticks/ [Kernel PMU event]
[...]
然后:
$ perf -e "uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/" <program> <arguments>
将报告从内存控制器#0 读取和写入操作时从主内存传输到高速缓存的字节数。将该数字除以所用时间,即可得出所用平均内存带宽的近似值。