问题描述
我想在我的应用程序中检索DRAM 访问次数。准确地说,我需要区分数据和代码访问。处理器是一个 Intel(R) Core(TM) i7-4720HQ cpu @ 2.60GHz
(Haswell
)。根据 Intel Software Developer's Manual,Volume 3 和 Perf
,我可以查找和分类以下内存访问相关事件:
(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-misses
和LLC-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_dram
和any_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
是映射到本机事件perf
的OFFCORE_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 数据加载预取,而不是所有数据加载硬件和软件预取。