编程填充我们系统的L1或L2缓存

4
我们如何系统地编写代码来将数据加载到我们的L1或L2缓存中?
我特别想针对我的系统填充L1 I缓存以进行一些更高级的分析。任何建议都可以-无论是编写汇编代码还是简单的C编程。关于此主题的相关文章将更加有帮助。

https://dev59.com/4HA75IYBdhLWcg3wJFmY - Nobilis
3个回答

3

缓存存储最近访问的数据。要填充缓存,只需访问数据。或者在这种情况下,访问指令。用无操作指令(以及一个循环分支指令)填充一块内存,然后跳转到它。

棘手的部分是一旦加载了数据,就要保持数据在其中。只要您的基准测试正在运行,就不能访问32K(或其他大小)数据集之外的任何内容。

我无法想象从人工填充缓存并随后使用相同数据集保持其填充的结果会得到什么,但是就是这样。


有没有可能检查L1 I高速缓存是否已满?是否有某种与我运行test.asm相关的内存统计信息?(假设我的test.asm有足够的nop指令来填充32K I高速缓存,并且这里假设没有循环执行) - user2478142
这将假定一个完全关联的高速缓存(即使在广告中宣传,CPU也几乎从不作弊),以及纯LRU替换策略(它们几乎从不是)和没有分离的I / D高速缓存(许多CPU今天仍然有),以及在基准测试运行时操作系统不执行任何操作(操作系统总是在最不方便的时间运行)。 - Art

2
你需要找出你的CPU缓存关联性和替换策略。我无法想出一个通用的解决方案,适用于我使用过的所有CPU。即使是宣传为完全关联的LRU替换策略的高速缓存,在现实中也并非如此,很难找出完全填满高速缓存的内存访问模式。
如果你想要这个针对某些特定基准测试(出于其他原因这是个坏主意),我建议你尝试弄清如何清除缓存。这确实可行。

我正在使用Ubuntu系统。使用lscpu指令可以准确地显示我的分裂缓存布局和大小分配情况。此外,通过检查系统设备设置(例如通过命令“cd /sys/devices/system/cpu/cpu0/cache/index0”),可以获取与缓存结构相关的所有详细信息(级别、一致性和关联性)。 - user2478142
你认为应该如何解决这个问题 - 假设我已经了解了我的缓存的这些特性。 - user2478142
鉴于结合性、缓存行自、缓存大小和替换策略,有时(但不总是)可能可以找出一种访问模式来填满缓存。这是一篇讲解高速缓存的不错的文章。但请注意,大多数高速缓存都是物理的,而您很可能正在使用虚拟内存。操作系统不会给您精心对齐的内存。更好的方法是弄清楚如何刷新缓存,因为在大多数系统上都可以实现这一点,并将缓存置于已知状态。 - Art
真正的问题是:你试图解决什么问题?在操作系统上运行时,在基准测试期间保持缓存处于已知状态非常困难。 - Art
我的目标是获取内存统计数据(我的L1 I高速缓存的平均内存访问时间)- 为此,我希望完全填充我的缓存,并使用rdtsc指令计算统计数据。 - user2478142

0

上周我刚完成了对L1和L2缓存进行ECC填充的任务。

基本上,如果你有一个64K字节的缓存,例如,总共(x个路,y个缓存行等等)对于数据只需通过缓存线性地访问那么多数据(可能需要打开MMU以启用缓存),从某个64K字节边界开始,并理想情况下读取64K字节的数据,如果可能的话,使用缓存行大小的读取(或其倍数)。对于icache,你需要那么多字节的指令(nop或add reg+1之类),记住最后可能会有预取,因此你可能需要向后撤几条指令才能使预取将你带到末尾(这可能需要一些练习,如果你没有逻辑的可见性(芯片模拟),那么你可能找不到解决方法)。

你可以使用MMU或其他游戏逻辑来减少所需的内存量,例如,如果你有一个覆盖4Kb的条目大小的MMU,那么你可以用4Kb的真实内存填充数据,然后使用16个不同的MMU条目(具有16个不同的虚拟地址),并且对于每个16个读取通过4K。当然,这是在你的缓存位于MMU虚拟地址侧的情况下。

总的来说,这种做法有点丑陋,如果你的MMU防止指令缓存,你可以将执行测试的代码放在非缓存空间中,以便它不会干扰ICache,只有用于填充缓存的指令在缓存地址空间中。

祝你好运...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接