你能帮我理解 ARM Cortex-A9 上的缓存行为吗?
Can you help me understand the cache behaviour on an ARM Cortex-A9?
我试图了解在 LOAD and/or STORE 指令期间发生了什么。因此,我执行了 4 次测试,每次,我测量了 cpu 周期数 (CC) / 缓存命中 (CH) / 未命中 (CM) / 数据读取 (DR) / 写入 (DW)。
读取不同的计数器后,我只是刷新 L1(I/D 缓存)。
测试 1:
LDRB R3, [R4,#1]!
STR R3, [SP,#0x48+var_34]
Results: 4 (CC) 3(CH) 1(CM) 1(DR) 2(DW)
测试 2:
LDR R3, [SP,#0x48+var_34]
LDR R3, [R3]
Results: 4 3 1 2 1
测试 3:
LDR R3, [SP,#0x48+var_38]
LDR R3, [R3]
STR R3, [SP,#0x48+var_30]
Results: 4 4 1 2 2
var_30 is returned at the end of the current function.
测试 4:
LDR R2, [SP,#0x48+var_34]
LDR R3, [R2]
Results: 4 3 1 2 1
这是我的理解:
1.缓存未命中
在每个测试中,我们有 1 个缓存未命中,因为当一个执行时
LDR reg, something
"Something"要缓存,会出现缓存未命中
而且...这几乎是我能做出的唯一 "logical" 解释...
我不明白缓存命中、数据读取和数据写入的不同值。
有什么想法吗?
infocenter.arm.com 的 arm 文档在 amba/axi 文档中非常清楚地说明了 axi/amba 总线上发生的情况。现在处理器与 L1 紧密耦合,而不是 amba/axi,都在内核中。如果您只清除 L1,那么 L2 可能仍包含这些值,因此无论 L2 是否遗漏,与其他实验相比,一个实验可能会显示不同的结果。此外,您不仅在测量加载和存储,而且还在测量指令的获取,即使有两条指令,如果缓存行在它们之间,它们的对齐也会改变结果,性能可能与它们在一起时不同。有一些实验是基于一行内的对齐来做的,关于何时以及是否有另一个缓存行提取。
此外,尝试在此类处理器上获得确定性数字也有点困难,尤其是在启用缓存的情况下。如果您 运行 这些实验不是在裸机上进行的,那么就没有理由期待任何有意义的结果。对于裸机,结果仍然令人怀疑,但可以使其更具确定性。
如果您只是想了解不特定于 arm 或任何其他平台的缓存基础知识,那么只需 google 那个,去维基百科等。那里有大量信息。缓存只是更快的 ram,在时间上更接近处理器,而且速度更快(更昂贵)sram。所以很简单,缓存会查看您的地址,在 table 或一组 table 中查找并确定命中或未命中,如果命中则它 returns 值或接受写入数据并完成事务的处理器端(允许处理器继续但随后去写入缓存,基本上是触发和忘记)。如果未命中,则它必须弄清楚缓存中是否有用于此数据的备用开口,如果没有,则必须通过将其写出来驱逐某些内容,然后或者如果已经有空位,则可以读取缓存行这通常比您要求的读数大。它以与 l1 相同的方式击中 l2,击中或未击中逐出或不击中等等,直到它击中获得命中的缓存层或直到它击中它从中获取数据的最终 ram 或外围设备。然后在返回 l1 的过程中将其写入所有缓存层,然后处理器获得它所要求的少量数据。如果处理器现在在该缓存行中请求另一个数据项,它在 l1 中并且 returns 非常快。 l2 通常大于 l1 等等,这样 l1 中的所有内容都在 l2 中但不是 l2 中的所有内容都在 l1 中,这样您就可以从 l1 驱逐到 l2,如果出现某些情况,它可能会错过 l1 但会命中 l2 并且仍然比去慢 dram 快得多。这有点像把工具或参考资料或任何你最常使用的东西放在办公桌上离你更近,而你不经常放的东西离你更远,因为没有空间容纳所有东西,因为你改变项目或发展最常用的东西,最不经常变化的是桌子上的位置变化。
我试图了解在 LOAD and/or STORE 指令期间发生了什么。因此,我执行了 4 次测试,每次,我测量了 cpu 周期数 (CC) / 缓存命中 (CH) / 未命中 (CM) / 数据读取 (DR) / 写入 (DW)。
读取不同的计数器后,我只是刷新 L1(I/D 缓存)。
测试 1:
LDRB R3, [R4,#1]!
STR R3, [SP,#0x48+var_34]
Results: 4 (CC) 3(CH) 1(CM) 1(DR) 2(DW)
测试 2:
LDR R3, [SP,#0x48+var_34]
LDR R3, [R3]
Results: 4 3 1 2 1
测试 3:
LDR R3, [SP,#0x48+var_38]
LDR R3, [R3]
STR R3, [SP,#0x48+var_30]
Results: 4 4 1 2 2
var_30 is returned at the end of the current function.
测试 4:
LDR R2, [SP,#0x48+var_34]
LDR R3, [R2]
Results: 4 3 1 2 1
这是我的理解:
1.缓存未命中
在每个测试中,我们有 1 个缓存未命中,因为当一个执行时
LDR reg, something
"Something"要缓存,会出现缓存未命中
而且...这几乎是我能做出的唯一 "logical" 解释... 我不明白缓存命中、数据读取和数据写入的不同值。
有什么想法吗?
infocenter.arm.com 的 arm 文档在 amba/axi 文档中非常清楚地说明了 axi/amba 总线上发生的情况。现在处理器与 L1 紧密耦合,而不是 amba/axi,都在内核中。如果您只清除 L1,那么 L2 可能仍包含这些值,因此无论 L2 是否遗漏,与其他实验相比,一个实验可能会显示不同的结果。此外,您不仅在测量加载和存储,而且还在测量指令的获取,即使有两条指令,如果缓存行在它们之间,它们的对齐也会改变结果,性能可能与它们在一起时不同。有一些实验是基于一行内的对齐来做的,关于何时以及是否有另一个缓存行提取。
此外,尝试在此类处理器上获得确定性数字也有点困难,尤其是在启用缓存的情况下。如果您 运行 这些实验不是在裸机上进行的,那么就没有理由期待任何有意义的结果。对于裸机,结果仍然令人怀疑,但可以使其更具确定性。
如果您只是想了解不特定于 arm 或任何其他平台的缓存基础知识,那么只需 google 那个,去维基百科等。那里有大量信息。缓存只是更快的 ram,在时间上更接近处理器,而且速度更快(更昂贵)sram。所以很简单,缓存会查看您的地址,在 table 或一组 table 中查找并确定命中或未命中,如果命中则它 returns 值或接受写入数据并完成事务的处理器端(允许处理器继续但随后去写入缓存,基本上是触发和忘记)。如果未命中,则它必须弄清楚缓存中是否有用于此数据的备用开口,如果没有,则必须通过将其写出来驱逐某些内容,然后或者如果已经有空位,则可以读取缓存行这通常比您要求的读数大。它以与 l1 相同的方式击中 l2,击中或未击中逐出或不击中等等,直到它击中获得命中的缓存层或直到它击中它从中获取数据的最终 ram 或外围设备。然后在返回 l1 的过程中将其写入所有缓存层,然后处理器获得它所要求的少量数据。如果处理器现在在该缓存行中请求另一个数据项,它在 l1 中并且 returns 非常快。 l2 通常大于 l1 等等,这样 l1 中的所有内容都在 l2 中但不是 l2 中的所有内容都在 l1 中,这样您就可以从 l1 驱逐到 l2,如果出现某些情况,它可能会错过 l1 但会命中 l2 并且仍然比去慢 dram 快得多。这有点像把工具或参考资料或任何你最常使用的东西放在办公桌上离你更近,而你不经常放的东西离你更远,因为没有空间容纳所有东西,因为你改变项目或发展最常用的东西,最不经常变化的是桌子上的位置变化。