Linux 下如何关闭 CPU cache?

2020-07-18 11:25:02 +08:00
 vcfghtyjc

为了避免由于数据在不同层的 cache 所带来的运行时间的差异,我想要关闭 CPU cache,让所有数据都存在 DRAM 里。稍微搜索了一下,好像没什么清晰的解决方案,想问问有没有大神知道如何做。

谢谢!

10287 次点击
所在节点    Linux
108 条回复
vk42
2020-07-19 00:43:34 +08:00
@vcfghtyjc
Cache Disable 的行为是很确定的,在 Intel Manual 里面写的也很清楚,不用管 @realpg 故弄玄虚。
关键问题是大家对你关 Cache 来做 profiling 的需求有质疑,不知道你是不是已经用过 perf 之类的工具测试过,为什么一上来就关 cache 不太能理解……
reus
2020-07-19 00:45:27 +08:00
根据#45 楼的补充,楼主是想在多次运行同一段程序时,消除缓存带来的抖动
楼主想出的办法是关闭 cpu 缓存,但这个实际是偏离了原本的问题
原本的问题,搜 x86 performance benchmark flush cache 会有答案


拿着十年前的半桶水知识就来指点江山,呵呵
是,全世界就你知道 cpu 有 bug,这两年的什么 meltdown 、什么 specture,现代的年轻人都一无所知的!
恶臭。
vcfghtyjc
2020-07-19 00:51:29 +08:00
@reus 谢谢提供的信息,消消气哈。(>▽<)

我搜了一下,看到了一篇在 stack overflow 的帖子

https://stackoverflow.com/questions/48527189/is-there-a-way-to-flush-the-entire-cpu-cache-related-to-a-program

您指的是这个吗?还是有更好的资料呢?
vcfghtyjc
2020-07-19 00:52:14 +08:00
@vk42 确实不是很熟悉这一领域,有什么好用的工具可以推荐推荐吗?
reus
2020-07-19 01:00:09 +08:00
@vcfghtyjc 最简单的,跑完一次,去读一下其他地方的没用内存,让 cpu 缓存填满这些没用的数据,然后再继续下一次,这样可以保证 cpu 不会命中上一次留下的。看你 cpu 的 L3 多大,读个几兆几十兆应该就能填满。
例如一开始就 malloc 一块,然后测试完一次,memcpy 这块。
vk42
2020-07-19 01:01:47 +08:00
@vcfghtyjc perf 是比较常用的,而且比较方便,随手 perf stat 跑一下就能得到大概的数据,不过这个依赖你的 CPU 集成的 PMC 有哪些。如果上牛刀的话 Intel 的 U 有自家的 VTune,AMD 应该也有类似的商业工具。
helloworld000
2020-07-19 01:04:43 +08:00
@vcfghtyjc 时间太久具体记不清了, 我记得是区别不是很大....其实这玩意很看你 use case

如果是几 ms 级别的 latency 会有明显区别, 不然没什么意义
reus
2020-07-19 01:11:10 +08:00
@vcfghtyjc 你给的链接里面,就提到一个办法是 touching a lot of memory,这个应该是最简便的了,都不需要什么特权指令。但是这个似乎也不完全可靠,因为操作系统可能会将进程调度到另一个 cpu,这样就白填了。可能设一下 cpu affinity 会减少这类调度。
其实,我感觉这个也不是最初的问题。你说的“运行多次”,究竟是多少次?我觉得,只要运行足够多,例如几十万上百万次,缓存带来的抖动,就会被稀释,似乎不需要刻意消除。如果只是跑了几次几十次,那抖动就可能显著了。
vcfghtyjc
2020-07-19 01:17:40 +08:00
@reus 运行上百万次,我想要研究的是带来抖动的因素,所以想先排除 locality 带来的抖动。
vcfghtyjc
2020-07-19 01:19:51 +08:00
@helloworld000 目前标准差大概在 1000 ns 左右,不过我是想计算的是程序里一段代码的运行时间,这段代码会被执行数百万次,可能重启不能解决我的问题。
reus
2020-07-19 01:35:35 +08:00
@vcfghtyjc 那你只要精细分配好每次用到的内存,保证各次不出现共用 cache line 的情况就行了,locality 自然不生效。就不知道你的程序能不能完全自己控制分配了。
reus
2020-07-19 01:44:28 +08:00
@vcfghtyjc 场景就是类似避免 false sharing,但你这里不是多个线程共用 cache line 的问题,而是多次运行共用 cache line 的问题。而且涉及的是一次运行用到的全部内存,不能和另一次有任何共享 cache line 。我想到的是提前分配好各次需要用到的内存,然后再开始跑。内存分配器可能要自己写,因为一般的内存分配器都是尽量利用 cache locality,和你的目的完全相反……
zxdhuge
2020-07-19 02:34:56 +08:00
其实我还挺好奇,对于 multi core 的 CPU,各个 core 之间的 cache 是如何 synchronize 的,毕竟 process 可能一会在这个 core,过一会被分到了另一个 core
dartabe
2020-07-19 02:59:47 +08:00
应该是缓存命中的问题带来的抖动? 现在 x86 还有寄存器直连外部 dram 的吗? 应该都是要经过 cpu 缓存吧 1 级 2 级 3 级
tianshilei1992
2020-07-19 03:24:14 +08:00
@zxdhuge 所以 false sharing 就来了…
vcfghtyjc
2020-07-19 04:36:53 +08:00
@reus 感觉这个工程量有点大,是不是只有 C 语言程序做的到?
nifury
2020-07-19 06:33:31 +08:00
@vcfghtyjc #70 直觉上 1000ns 的标准差……有没有可能是系统调度导致的呢?
感觉 OS 的影响比 cache 大得多吧?
ryd994
2020-07-19 06:51:46 +08:00
@zxdhuge 操作系统进程调度频率相对缓存命中来说已经很低了。而且一般会尽量避免在两个核之间来回调度。
但是如果你自己的多线程程序写的不好,那又是另一回事了。
再说了,L3 共用。除非两个核互相 false sharing,否则同一个线程偶尔换一下无所谓的。

@vcfghtyjc 你先考虑调度的抖动吧。还有各种设备的中断。超算所以用的都是魔改版 Linux 。所有系统功能能关的都关掉。基本上就是只留个内存管理

@reus #71 这不叫 false sharing,因为确实是 by design 在 share 。解决办法很简单:不要释放上一次使用的内存就好。又或者每次使用前保证初始化内存。保证内存在缓存里比保证内存不在缓存里简单。
ryd994
2020-07-19 06:55:22 +08:00
@vcfghtyjc #45
你甚至可以加一个捣乱用的线程专门把别的线程的内存 invalidate 掉.....
vcfghtyjc
2020-07-19 06:59:32 +08:00
@ryd994 调度的抖动,能展开讲一下吗?这些只保留内存管理的魔改 Linux 有开源的吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/691081

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX