【问题标题】:Can the Intel performance monitor counters be used to measure memory bandwidth?英特尔性能监视器计数器能否用于测量内存带宽?
【发布时间】:2018-05-16 16:59:23
【问题描述】:

英特尔 PMU 能否用于测量每核读/写内存带宽使用情况?这里的“内存”指的是 DRAM(即,不命中任何缓存级别)。

【问题讨论】:

    标签: performance x86 intel-pmu memory-bandwidth


    【解决方案1】:

    是的(ish),间接的。您可以使用计数器之间的关系(包括时间戳)来推断其他数字。例如,如果您对 1 秒的间隔进行采样,并且有 N 个最后一级 (3) 缓存未命中,那么您可以非常确定每秒占用了 N*CacheLineSize 个字节。

    将其准确地与程序活动关联起来会有点棘手,因为这些未命中可能反映了 cpu 预取、中断活动等。

    还有一个“除非这个配置位处于这个状态,否则这个 cpu 不算数(MMX、SSE、AVX、..)”的泥潭;因此自己滚动很麻烦....

    【讨论】:

      【解决方案2】:

      是的,这是可能的,尽管它不一定像编程通常的 PMU 计数器那样简单。

      一种方法是使用通过 PCI 空间访问的可编程内存控制器计数器。一个好的起点是在pcm-memorypcm-memory.cpp 中检查英特尔自己的实现。这个应用程序向您展示了每个插槽或每个内存控制器的吞吐量,这适用于某些用途。特别是,带宽在所有内核之间共享,因此在安静的机器上,您可以假设大部分带宽与被测进程相关联,或者如果您想在套接字级别进行监控,这正是您想要的。

      另一种选择是对“offcore repsonse”计数器进行仔细编程。据我所知,这些与 L2(最后一个核心私有缓存)和系统其余部分之间的流量有关。您可以按核心响应的结果进行过滤,因此您可以使用各种“L3 未命中”事件的组合并乘以高速缓存行大小来获得读写带宽。这些事件的粒度非常细,因此您可以通过首先导致访问的原因进一步细分:指令获取、数据需求请求、预取等。

      非核心响应计数器在 perf 和 likwid 等工具的支持方面通常落后,但至少最近的版本似乎有合理的支持,即使对于像 SKL 这样的客户端部件也是如此。

      【讨论】:

        【解决方案3】:

        核心外响应性能监控工具可用于计算来自特定核心的 IDI 上所有源自核心的请求。请求类型字段可用于统计特定类型的请求,例如需求数据读取。但是,要测量每个内核的内存带宽,必须以某种方式将请求数转换为每秒字节数。大多数请求都是高速缓存行大小,即 64 字节。其他请求的大小可能未知,并且可能会向内存带宽添加小于或大于高速缓存行大小的字节数。其中包括高速缓存行拆分锁定请求、WC 请求、UC 请求和 I/O 请求(但这些不会增加内存带宽),以及需要完成所有挂起写入的围栏请求(MFENCE、@987654332 @,以及序列化指令)。

        如果您只对可缓存带宽感兴趣,那么您可以计算可缓存请求的数量并将其乘以 64 字节。这可能非常准确,假设可缓存的高速缓存行拆分锁定请求很少见。不幸的是,当前任何微架构上的核心外响应工具都无法计算从 L3(或 L4,如果可用)到内存的回写。原因是这些写回不是源自核心,通常是由于 L3 中的冲突未命中而发生的。因此,可以计算在 L3 中丢失并导致回写的请求,但核心外响应工具无法让您确定对 L3(或 L4)的任何请求是否导致回写。这就是为什么不可能“按核心”计算回写到内存的原因。

        此外,核心外响应事件需要一个可编程的性能计数器,该计数器是 0、1、2 或 3 之一(但在禁用 hyptherhreading 时不是 4-7)。

        英特尔至强 Broadwell 支持许多资源控制器技术 (RDT) 功能。特别是它支持Memory Bandwidth Monitoring (MBM),这是准确测量每个内核的内存带宽的唯一方法。

        MBM 与非核心响应相比具有三个优势:

        • 它使您能够测量一个或多个使用资源 ID 标识的任务的带宽,而不仅仅是每个内核。
        • 它不需要通用可编程性能计数器之一。
        • 它可以准确测量本地或总带宽,包括回写到内存。

        offcore response 的优点是它支持请求类型、供应商类型和 snoop 信息字段。

        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开始,Linux中RDT的实现有significantly changed。

        在运行内核版本 4.16 的 BDW-E5(双插槽)系统上,我可以使用以下命令序列查看 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
        

        我的理解是自系统重置后计算字节数。

        请注意,默认情况下,被监控的资源是整个套接字。

        不幸的是,包括 MBM 在内的大多数 RDT 功能在支持它的 Skylake 处理器上都变成了buggy。根据SKZ4和SKX4:

        英特尔® 资源控制器技术 (RDT) 内存带宽监控 (MBM) 不计算到本地的可缓存回写流量 记忆。这导致 RDT MBM 功能在计数总数下 消耗的带宽。

        这就是为什么在 Skylake-X 和 Skylake-SP(它们是唯一支持 MBM 的 Skylake 处理器)上运行时在 Linux 上默认为 disabled 的原因。您可以通过将以下 parameter rdt=mbmtotal,mbmlocal 添加到内核命令行来启用 MBM。某些寄存器中没有启用或禁用 MBM 或任何其他 RDT 功能的标志。相反,这是在内核中的某些数据结构中跟踪的。

        在 Intel Core 2 微架构上,可以使用 BUS_TRANS_MEM 事件测量每个内核的内存带宽,如 here 所述。

        【讨论】:

        • Linux 实现是否可以使用您提到的“资源 ID”功能监控特定任务的 BW 使用情况?
        • @BeeOnRope 是的。 “读取监控数据”一节中讨论的示例展示了如何创建 RMID 并将其分配给一个或一组任务。
        【解决方案4】:

        在某些架构上,使用 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 的读写操作中从主内存传输到缓存的字节数。将该数字除以使用的时间,就可以得到所使用的平均内存带宽的近似值。

        【讨论】:

        • 我假设那些性能事件或等效事件是 intel_gpu_top -l 用于其 IMC MiB/s 读/写列的内容。
        【解决方案5】:

        我不确定 Intel PMU,但我认为您可以使用 Intel VTune Amplifier (https://software.intel.com/en-us/intel-vtune-amplifier-xe)。这个有很多性能监控工具(内存、cpu缓存、cpu)。也许这对你有用。

        【讨论】:

        • VTune 是一种用于使用硬件性能计数器(即 PMU = 性能监控单元)的工具。除非您可以解释如何 让 VTune 测量内存带宽,否则这不是一个有用的答案。 (VTune 是一个有用的工具,可以帮助查找缓存未命中热点和类似的东西,而且显然远远超出了简单记录性能计数器的范围。但这不是这个问题要问的。)
        猜你喜欢
        • 2018-08-17
        • 2021-08-25
        • 1970-01-01
        • 2023-02-19
        • 2019-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多