DRAM 访问的性能计数器

问题描述

我想在我的应用程序中检索DRAM 访问次数。准确地说,我需要区分数据和代码访问。处理器是一个 Intel(R) Core(TM) i7-4720HQ cpu @ 2.60GHz (Haswell)。根据 Intel Software Developer's Manual,Volume 3Perf,我可以查找分类以下内存访问相关事件:

(A)
LLC-load-misses                                    [Hardware cache event]
LLC-loads                                          [Hardware cache event]
LLC-store-misses                                   [Hardware cache event]
LLC-stores                                         [Hardware cache event]
=========================================================================
(B)
mem_load_uops_l3_miss_retired.local_dram          
mem_load_uops_retired.l3_miss  
=========================================================================
(C)
offcore_response.all_code_rd.l3_miss.any_response 
offcore_response.all_code_rd.l3_miss.local_dram   
offcore_response.all_data_rd.l3_miss.any_response 
offcore_response.all_data_rd.l3_miss.local_dram   
offcore_response.all_reads.l3_miss.any_response   
offcore_response.all_reads.l3_miss.local_dram     
offcore_response.all_requests.l3_miss.any_response
=========================================================================
(D)
offcore_response.all_rfo.l3_miss.any_response     
offcore_response.all_rfo.l3_miss.local_dram       
=========================================================================
(E)
offcore_response.demand_code_rd.l3_miss.any_response
offcore_response.demand_code_rd.l3_miss.local_dram
offcore_response.demand_data_rd.l3_miss.any_response
offcore_response.demand_data_rd.l3_miss.local_dram
offcore_response.demand_rfo.l3_miss.any_response  
offcore_response.demand_rfo.l3_miss.local_dram    
=========================================================================
(F)
offcore_response.pf_l2_code_rd.l3_miss.any_response
offcore_response.pf_l2_data_rd.l3_miss.any_response
offcore_response.pf_l2_rfo.l3_miss.any_response   
offcore_response.pf_l3_code_rd.l3_miss.any_response
offcore_response.pf_l3_data_rd.l3_miss.any_response
offcore_response.pf_l3_rfo.l3_miss.any_response

我的选择如下:

  • 似乎LLC-load-missesLLC-store-misses的总和 将返回整个 DRAM 访问(等效地,我可以使用 LLC-misses 中的 Perf)。
  • 对于仅限数据的访问,我使用了 mem_load_uops_retired.l3_miss。 它不包括商店,但似乎可以因为商店似乎 很多不那么频繁?!)。
  • 简单来说,LLC-load-misses - mem_load_uops_retired.l3_miss = DRAM Accesses for Code(因为代码只读)。

这些选择合理吗?


我的其他问题:(第二个是最重要的)

  • 什么是 local_dramany_response
  • 乍一看,group (C),是group的load事件的高分辨率版本(A)。但我的测试表明,前者 组中的事件频繁后者。例如,在一个简单基准测试中,offcore_response.all_reads.l3_miss.any_response 事件的数量LLC-load-misses两倍
  • 组 (E),属于 demand reads(即所有 non-prefetched 读取)。这是否意味着,例如:offcore_response.all_data_rd.l3_miss.any_response - offcore_response.demand_data_rd.l3_miss.any_response = 预取导致的 DRAM 读取访问

组 (D)包括Read for Ownership 操作(对于 Cache Coherency 协议)引起的 DRAM 访问事件。这似乎与我的问题无关

Group (F),计算由 L2-cache prefetcher 引起的 DRAM 读取次数,这也与我的问题无关。 >

解决方法

根据我对问题的理解,我建议在指定的处理器上使用以下两个事件:

  • OFFCORE_RESPONSE.ALL_READS.L3_MISS.LOCAL_DRAM:这包括所有可缓存的数据读取和写入事务以及所有代码获取事务,无论事务是由指令(已退出与否)或预取或任何类型发起的。每个事件都代表对内存控制器的 64 字节读取请求。
  • OFFCORE_RESPONSE.ALL_CODE_RD.L3_MISS.LOCAL_DRAM:这包括对 IMC 的所有代码获取访问。

(我认为对于不可缓存的代码获取请求,这两个事件都不会发生,但我没有对此进行测试,文档对此也不清楚。)

“数据访问”可以与“代码访问”分开测量,方法是从第一个事件中减去第二个事件。这两个事件可以在 Haswell 上的同一个逻辑核心上同时计数,无需多路复用。

当然还有其他交易确实进入了 IMC,但不计入上述两个事件中的任何一个。这些包括:(1) L3 写回,(2) 来自内核的不可缓存的部分读写,(3) 完全 WCB 驱逐,以及 (4) 来自 IO 设备的内存访问。根据工作负载,类型 (1)、(3) 和 (4) 的访问可能占对 IMC 的总访问的很大一部分。

看起来 LLC-load-misses 和 LLC-store-misses 的总和将 返回整个 DRAM 访问(等效地,我可以使用 LLC-misses 在 Perf 中)。

注意以下几点:

  • 事件 LLC-load-misses 是映射到本机事件 perfOFFCORE_RESPONSE.DEMAND_DATA_RD.L3_MISS.ANY_RESPONSE 事件。
  • 事件 LLC-store-misses 映射到 OFFCORE_RESPONSE.DEMAND_RFO.L3_MISS.ANY_RESPONSE

这些不是您想要的事件,因为:

  • ANY_RESPONSE 位表示该事件可以针对针对任何单位的请求而发生,而不仅仅是 IMC。
  • 这些事件计算 L1 数据预取和页面遍历请求,但不计算 L2 数据预取。您通常需要计算消耗内存带宽的所有预取。

对于纯数据访问,我使用了 mem_load_uops_retired.l3_miss。它确实 不包括商店,但似乎还可以(因为商店似乎很多 不那么频繁?!)。

在 Haswell 上使用 mem_load_uops_retired.l3_miss 有很多问题:

  • 此事件存在不可靠的情况,因此如果有替代方案,则应避免。否则,分析方法应考虑此事件计数的潜在不可靠性。
  • 该事件仅针对来自已停用加载的请求发生,并且会忽略可能很重要的推测加载和所有存储。
  • 以有意义的方式对这些事件和其他事件进行算术运算并不容易。例如,您建议执行“LLC-load-misses - mem_load_uops_retired.l3_miss = DRAM Accesses for Code”是不正确的。

local_dram 和 any_response 是什么?

并非所有在 L3 中未命中的请求都会转到 IMC。一个典型的例子是内存映射 IO 请求。您说您只想要发送到 IMC 的核心请求,所以 local_dram 是正确的。

乍一看,(C)组似乎是更高分辨率的版本 组 (A) 的负载事件。但是我的测试表明 前一组比后者更频繁。例如,在一个 简单的基准,数量 offcore_response.all_reads.l3_miss.any_response 事件是原来的两倍 许多为 LLC 加载未命中。

这是正常的,因为 offcore_response.all_reads.l3_miss.any_response 包含 LLC-load-misses 并且很容易变得更大。

组 (E),属于按需读取(即所有非预取读取)。 这是否意味着,例如: offcore_response.all_data_rd.l3_miss.any_response - offcore_response.demand_data_rd.l3_miss.any_response = DRAM 读取 预取导致的访问?

不,因为:

  • any_response 位,如上所述,
  • 此减法仅导致 L2 数据加载预取,而不是所有数据加载硬件和软件预取。