为了避免由于数据在不同层的 cache 所带来的运行时间的差异,我想要关闭 CPU cache,让所有数据都存在 DRAM 里。稍微搜索了一下,好像没什么清晰的解决方案,想问问有没有大神知道如何做。
谢谢!
1
yangbonis 2020-07-18 11:27:36 +08:00 via iPhone
cpu 没有提供这个功能,cache 就是 cpu 的一部分,下电就关了
|
2
venster 2020-07-18 11:31:21 +08:00 via iPhone 2
Q:北京到上海的高铁太密集,场站员工抱怨压力大
A:没问题,这就把高铁停了 |
3
dalabenba 2020-07-18 11:33:46 +08:00 via Android
/proc/iomem 获取分布信息,/proc/mtrr 改
|
4
nightwitch 2020-07-18 11:35:06 +08:00
cpu cache 是 cpu 的组成元件,这还能关掉的? 你先说清楚是什么问题导致你有这个需求,大伙再来讨论解决方案
|
5
nightwitch 2020-07-18 11:42:31 +08:00
gcc 内置的__builtin___clear_cache,__builtin_prefetch 以及 Linux 的 cacheflush 可能有点用。
|
6
dalabenba 2020-07-18 11:45:34 +08:00 via Android
@dalabenba 当然你要排除是不是 cache 的影响速度的话应该用 perf 去看 cache miss 率而不是关 cache,毕竟代码都是越快越好
|
7
vcfghtyjc OP @dalabenba 谢谢。能否详细说一下怎么使用吗?我通过 `/proc/iomem` 看到了各个硬件设备的内存,但是没看到 cpu 的 cache 。
|
8
vcfghtyjc OP @dalabenba 因为系统里还有其他影响因素,我是希望先关掉 cache,避免由于 locality 带来的干扰。
|
9
vk42 2020-07-18 11:57:35 +08:00
赞成#6,除了调试 CPU bug 的基本没见过关 cache 来做 performance profiling 的,你只是没找到对的工具和方法。
现在 CPU 关 cache 非常 tricky,以前老型号还有能在 BIOS 里全局关的 |
10
misaka19000 2020-07-18 11:58:31 +08:00
你能保证操作系统在进程 schedule 的进程运行时间一致吗,如果这个都保证不了就先不要考虑 CPU 的 cache 了
|
11
Nich0la5 2020-07-18 12:04:33 +08:00 via Android
这是什么魔鬼需求还需要关 cache 的?
|
12
wnpllrzodiac 2020-07-18 12:05:48 +08:00 via Android
cache 速度比内存都快,没了 cache cpu 就变渣渣了啊
|
13
Juszoe 2020-07-18 12:22:42 +08:00
关闭 cache,这速度不得倒退十几年
|
14
em70 2020-07-18 12:26:33 +08:00
说得好像你知道 CPU cache 里存的是啥一样
|
15
kokutou 2020-07-18 12:32:48 +08:00 2
没了 cache,开机怕是都要 2 小时
|
16
tempdban 2020-07-18 12:45:34 +08:00 via Android
兄弟,就算是关闭了广义的 cache,cpu 里边的另一些 cache 你是永远关不掉的,如果你有性能优化有关的问题,可以尝试联系我
|
17
nevin47 2020-07-18 13:04:18 +08:00 via Android
LZ 你要知道,当前主流 CPU 的 architecture 决定了数据本来就是层层透过 cache 到达 cpu 里面的,完全 disable cacheline 是几乎不可能的,不过实在想这么玩,可以魔改一下 mm,让你所有拿到的内存都标记上 nocache,这样每次内存语义都会从内存同步一次
|
18
aijam 2020-07-18 13:10:04 +08:00
|
19
realpg 2020-07-18 13:12:18 +08:00 1
真是鸟大了啥林子都见过了……
|
20
reus 2020-07-18 13:17:34 +08:00 1
你们都不会用搜索引擎的吗?
这样搜:disable cpu L1 cache 然后你就会发现这个: https://stackoverflow.com/questions/48360238/how-can-the-l1-l2-l3-cpu-caches-be-turned-off-on-modern-x86-amd64-chips 和这个: https://unix.stackexchange.com/questions/316684/how-to-disable-processors-l1-and-l2-caches |
21
sunnybird 2020-07-18 13:18:18 +08:00 via Android
大佬在做啥子呢
|
22
Dox 2020-07-18 13:21:00 +08:00 via iPad
你这问题和“怎么让电脑拔了内存还能运行”差不多
|
23
ghostheaven 2020-07-18 13:34:48 +08:00 via Android
google 一下,有个 kernel module 可以做这个事情
https://unix.stackexchange.com/questions/316684/how-to-disable-processors-l1-and-l2-caches |
24
realpg 2020-07-18 13:35:51 +08:00
|
25
reus 2020-07-18 13:44:16 +08:00 2
@realpg 我不知道你在说什么。反正 intel 手册里是这样写的:
11.5.3 Preventing Caching To disable the L1, L2, and L3 caches after they have been enabled and have received cache fills, perform the following steps: 1. Enter the no-fill cache mode. (Set the CD flag in control register CR0 to 1 and the NW flag to 0. 2. Flush all caches using the WBINVD instruction. 3. Disable the MTRRs and set the default memory type to uncached or set all MTRRs for the uncached memory type (see the discussion of the discussion of the TYPE field and the E flag in Section 11.11.2.1, “IA32_MTRR_DEF_TYPE MSR”). The caches must be flushed (step 2) after the CD flag is set to insure system memory coherency. If the caches are not flushed, cache hits on reads will still occur and data will be read from valid cache lines.The intent of the three separate steps listed above address three distinct requirements: (i) discontinue new data replacing existing data in the cache (ii) ensure data already in the cache are evicted to memory, (iii) ensure subse-quent memory references observe UC memory type semantics. Different processor implementation of caching control hardware may allow some variation of software implementation of these three requirements. See note below. 或者你可以只看第一句:“To disable the L1, L2, and L3 caches ”。 |
26
imbushuo 2020-07-18 14:41:05 +08:00
@reus 从程序员的角度,cache 被关掉了;从架构的角度,cache 还是在那里,data path 没有改变(所以看怎么理解了
|
27
realpg 2020-07-18 14:48:18 +08:00
@reus #25
AMD 我是不清楚。 你对 Intel CPU 的机制一无所知,就单纯看了那个标题,就觉得你懂了而已。 既然你啥也不懂,所以我就告诉你结论好了。 经过 intel 手册的这个操作,L3 Cache 会变成什么样我不清楚,因为我折腾这玩意的时代,只有服务器 CPU 有 L3,普遍 CPU 只有 L2,而且 L1 L2 这几年的机制和特性都没变化。在这些操作以后,L1 L2 会变成跟 RAM 一样的用途,然后速度比 RAM 快很多。 如果不经过这个操作,L1 L2 并不是一种超快的 RAM,是要参与 CPU 逻辑的。 |
29
realpg 2020-07-18 14:58:46 +08:00 2
@nevin47 #28
现代的年轻人很少经历 CPU 级 BUG,所以对这些都一无所知。 不过估计未来国产 X86 低端 CPU 开卖+政采多了以后,估计就要回到我们瞎折腾那个年代,会遭遇 CPU BUG…… 然后就有机会了解底层 CPU 流程,各种汇编底层开关了 |
30
inframe 2020-07-18 16:04:23 +08:00
最快的 SRAM 放着不用,要走总线直接读写 DRAM ?
|
33
xyjincan 2020-07-18 16:42:28 +08:00
System.sleep(1000)
|
34
dalabenba 2020-07-18 17:02:28 +08:00 via Android 2
@vcfghtyjc iomem 里面是内存布局,system ram 就是,cache 是要修改页表属性的,在 bios 阶段会设置 mtrr,起来后修改对于应页表的 pat 来区分 cache 行为的,我也没试过在运行状态下修改 mtrr
你可以说下如果关了 cache 你预期会出现什么结果,你能得到什么结论,说不定有别的办法 |
35
cheng6563 2020-07-18 17:04:39 +08:00
现代的 CPU 桌面 CPU 保证不了运行时间一致吧
|
36
DoctorCat 2020-07-18 17:29:51 +08:00
让 v2 少一些争吵,英特尔社区给你参考: https://software.intel.com/en-us/comment/1746645
|
38
wangritian 2020-07-18 19:31:51 +08:00 1
避免程序运行过快?
|
39
barrysn 2020-07-18 19:37:22 +08:00
建议去翻一遍计算机组成原理
|
40
lonewolfakela 2020-07-18 20:34:54 +08:00
要搞这种级别的 profiling 的话,一般都是弄个 gem5 之类的 cpu 仿真器吧……
|
41
realpg 2020-07-18 20:42:51 +08:00 1
@ryncsn #37
CPU 层面对于内存的使用,并不都是你主动 malloc 的分配 这是他内管理的 对于 data 的逻辑缓存 nfc 打开或者在指令传递时候打上 no cache 标志 就不会在 cache 里面留下 hot cache 但是不代表不继续使用数据和指令的 L1 以及大 L2 cache |
42
Nadao 2020-07-18 21:46:09 +08:00
在还是 DIY 电脑为主流的年代,BIOS 里面就可以关了 L1/L2 。但关了会非常非常慢。
|
43
systemcall 2020-07-18 22:30:31 +08:00 via Android
|
44
lxilu 2020-07-18 23:47:22 +08:00 via iPhone
其他处理器加速功能呢?
|
45
vcfghtyjc OP @dalabenba 目前我运行同一段代码多次,通过 KNN 我们可以将代码运行时间分成 4 个 clusters,cpu 的型号显示有三层 cache,我就想通过关闭 cache,观察运行时间是否还会被分为 4 个 clusters 。
|
46
vcfghtyjc OP @Nadao 现在是否有支持关闭 L1/L2 的 BIOS 。我看到有方法是这么说的,也有人说运行状态下无法关闭 cache 。
|
47
helloworld000 2020-07-19 00:10:34 +08:00
如果是做实验的话, 最直接的办法就是每次跑这个程序的时候都重启一次电脑
|
48
vcfghtyjc OP @realpg 看起来经过 intel 文档里的方法,数据依然会从 DRAM 经过 L3/L2/L1 cache 到 CPU ?是否可以理解为所有数据都是从 DRAM 经过 cache 到 CPU,他们移动的距离是一样的?
|
49
samuel 2020-07-19 00:13:21 +08:00
禁用了 cpu cache 的测试结果没有实际意义,没有人会这么用,因为实在是太慢了
|
50
vcfghtyjc OP @helloworld000 是个方法。不过我的实验环境应该没有别的应用在运行(除了操作系统的),不知道会有多少提升。
|
51
helloworld000 2020-07-19 00:23:23 +08:00
|
52
realpg 2020-07-19 00:26:15 +08:00 3
@vcfghtyjc #48
距离一样,但是时间是不一样的。 我其实也不是搞这个的,只是早年参与调试过 cpu bug,跟 intel 的工程师一起搞过这些东西,他们会很通俗的给你讲这些东西。 这玩意怎么理解好呢,不太正确的说,默认的情况下,cache 的一部分功能是 cpu 直接执行单元的小 ram,不需要你关心,由 CPU 决定有些汇编指令的中间存储放进去,然后还有一部分功能比如指令缓存、数据缓存,这部分就是比较字面意义的 cache 了,还有一些复杂指令本身就不是一步指令,需要中间逻辑存储,或者一切其他需要执行切换场景,就会临时性的放进去,十年前这里面的功能就很复杂了。 这玩意是没法关闭的。就好像说,我不在乎慢,我不要 RAM 了,慢点我能忍,直接操作 SSD,是没有这种接口的。 实际上,CPU 的大部分通用功能的数据进口和出口就是这个 cache 。这里面具体的细节,就得跟 intel 工程师去聊了。 楼上那个嘴硬的,他引用那个帖子,就好像,你去手机店买手机,张嘴我要 256G 内存的,店员是不会非得 SB 似的纠正你那是 256G 硬盘,不是 256G 内存,他就给你一个 8+256 的手机,他知道你要干啥,或者说,最多能干到啥地步而已。 这里面的机制基本我是粗了解,我现在也是搞运维和架构设计的,我不需要了解到 CPU 具体咋工作,但是概念一定要有,仅此而已。 |
53
vcfghtyjc OP @helloworld000 效果和不重启比有很明显不同吗?
|
54
vcfghtyjc OP @realpg 距离感觉占了执行时间的很大一部分。目前程序的标准差大概是 1000 ns,如果保证了距离一样是否能减少到比如几百纳秒?
|
55
vk42 2020-07-19 00:32:38 +08:00 1
@realpg #27 #41
本来以为是大佬,结果看你后面回复原来是民科 CPU 专家……Intel 架构中 Cache Disable 不是指令上的 flag,而是 MMU 负责的。而且 x86 架构没有办法对 Cache 直接寻址,所以你说的当 RAM 用不可能。不过除 x86 以外是有类似用法的,比如 ARM 的 TCM,就是可以直接寻址的 SRAM 缓存 |
56
reus 2020-07-19 00:33:34 +08:00
@vcfghtyjc 你要的不是禁用缓存,是每次运行代码前 flush 缓存: https://stackoverflow.com/questions/1756825/how-can-i-do-a-cpu-cache-flush-in-x86-windows 。不用重启……
|
57
realpg 2020-07-19 00:36:55 +08:00
@vcfghtyjc #54
这些细节我不了解 基本我这边的相关经历都是 10 年以前 一个涉及 intel cpu 的 cache 的硬 bug 调试 我们运维的程序 当时跟 intel 的人协作过一阵子 当时他们给粗略的讲过 |
58
vcfghtyjc OP @vk42 我到不用把 cache 当 ram 用。看了这么多楼,已经不太懂 Intel 的 Cache Disable 到底做了什么。
|
59
vcfghtyjc OP @reus 因为我测得是程序的一段代码块的运行时间,是否有在运行中 flush cache 的指令?还是说我应该把这段代码块摘出来,然后重复运行多次?
|
61
vk42 2020-07-19 00:43:34 +08:00 1
|
62
reus 2020-07-19 00:45:27 +08:00 1
根据#45 楼的补充,楼主是想在多次运行同一段程序时,消除缓存带来的抖动
楼主想出的办法是关闭 cpu 缓存,但这个实际是偏离了原本的问题 原本的问题,搜 x86 performance benchmark flush cache 会有答案 拿着十年前的半桶水知识就来指点江山,呵呵 是,全世界就你知道 cpu 有 bug,这两年的什么 meltdown 、什么 specture,现代的年轻人都一无所知的! 恶臭。 |
63
vcfghtyjc OP @reus 谢谢提供的信息,消消气哈。(>▽<)
我搜了一下,看到了一篇在 stack overflow 的帖子 https://stackoverflow.com/questions/48527189/is-there-a-way-to-flush-the-entire-cpu-cache-related-to-a-program 您指的是这个吗?还是有更好的资料呢? |
65
reus 2020-07-19 01:00:09 +08:00
@vcfghtyjc 最简单的,跑完一次,去读一下其他地方的没用内存,让 cpu 缓存填满这些没用的数据,然后再继续下一次,这样可以保证 cpu 不会命中上一次留下的。看你 cpu 的 L3 多大,读个几兆几十兆应该就能填满。
例如一开始就 malloc 一块,然后测试完一次,memcpy 这块。 |
66
vk42 2020-07-19 01:01:47 +08:00
@vcfghtyjc perf 是比较常用的,而且比较方便,随手 perf stat 跑一下就能得到大概的数据,不过这个依赖你的 CPU 集成的 PMC 有哪些。如果上牛刀的话 Intel 的 U 有自家的 VTune,AMD 应该也有类似的商业工具。
|
67
helloworld000 2020-07-19 01:04:43 +08:00
|
68
reus 2020-07-19 01:11:10 +08:00
@vcfghtyjc 你给的链接里面,就提到一个办法是 touching a lot of memory,这个应该是最简便的了,都不需要什么特权指令。但是这个似乎也不完全可靠,因为操作系统可能会将进程调度到另一个 cpu,这样就白填了。可能设一下 cpu affinity 会减少这类调度。
其实,我感觉这个也不是最初的问题。你说的“运行多次”,究竟是多少次?我觉得,只要运行足够多,例如几十万上百万次,缓存带来的抖动,就会被稀释,似乎不需要刻意消除。如果只是跑了几次几十次,那抖动就可能显著了。 |
70
vcfghtyjc OP @helloworld000 目前标准差大概在 1000 ns 左右,不过我是想计算的是程序里一段代码的运行时间,这段代码会被执行数百万次,可能重启不能解决我的问题。
|
71
reus 2020-07-19 01:35:35 +08:00
@vcfghtyjc 那你只要精细分配好每次用到的内存,保证各次不出现共用 cache line 的情况就行了,locality 自然不生效。就不知道你的程序能不能完全自己控制分配了。
|
72
reus 2020-07-19 01:44:28 +08:00
@vcfghtyjc 场景就是类似避免 false sharing,但你这里不是多个线程共用 cache line 的问题,而是多次运行共用 cache line 的问题。而且涉及的是一次运行用到的全部内存,不能和另一次有任何共享 cache line 。我想到的是提前分配好各次需要用到的内存,然后再开始跑。内存分配器可能要自己写,因为一般的内存分配器都是尽量利用 cache locality,和你的目的完全相反……
|
73
zxdhuge 2020-07-19 02:34:56 +08:00
其实我还挺好奇,对于 multi core 的 CPU,各个 core 之间的 cache 是如何 synchronize 的,毕竟 process 可能一会在这个 core,过一会被分到了另一个 core
|
74
dartabe 2020-07-19 02:59:47 +08:00
应该是缓存命中的问题带来的抖动? 现在 x86 还有寄存器直连外部 dram 的吗? 应该都是要经过 cpu 缓存吧 1 级 2 级 3 级
|
75
tianshilei1992 2020-07-19 03:24:14 +08:00
@zxdhuge 所以 false sharing 就来了…
|
77
nifury 2020-07-19 06:33:31 +08:00
@vcfghtyjc #70 直觉上 1000ns 的标准差……有没有可能是系统调度导致的呢?
感觉 OS 的影响比 cache 大得多吧? |
78
ryd994 2020-07-19 06:51:46 +08:00 via Android 1
@zxdhuge 操作系统进程调度频率相对缓存命中来说已经很低了。而且一般会尽量避免在两个核之间来回调度。
但是如果你自己的多线程程序写的不好,那又是另一回事了。 再说了,L3 共用。除非两个核互相 false sharing,否则同一个线程偶尔换一下无所谓的。 @vcfghtyjc 你先考虑调度的抖动吧。还有各种设备的中断。超算所以用的都是魔改版 Linux 。所有系统功能能关的都关掉。基本上就是只留个内存管理 @reus #71 这不叫 false sharing,因为确实是 by design 在 share 。解决办法很简单:不要释放上一次使用的内存就好。又或者每次使用前保证初始化内存。保证内存在缓存里比保证内存不在缓存里简单。 |
79
ryd994 2020-07-19 06:55:22 +08:00 via Android
@vcfghtyjc #45
你甚至可以加一个捣乱用的线程专门把别的线程的内存 invalidate 掉..... |
81
ryd994 2020-07-19 07:16:02 +08:00 via Android
@vcfghtyjc 比如网络中断,定时器中断,这些都很常见。因为用户态其实优先级很低的,各种中断和内核线程都可以抢占。
如果线程数量少与可用的核数量的话操作系统一般不会随便把你的进程调度到其他核上。但是操作系统后台其实要干很多维护性的工作。又或者你虽然没有用这个功能,但操作系统还是默认在处理相关的逻辑。比如桌面平台为了保证用户体验,一般会把系统定时器的频率设得比较高。 具体可以看 IBM 在超算上 os jitter 相关的论文。 |
82
vcfghtyjc OP @ryd994 因为我程序是在单机上运行的,应该不太存在网络中断,目前都是单线程,cpu 数量肯定是足够 OS 做维护的,不知道会不会是定时器中断。
HPC 上的 jitter 和普通服务器 server 应该还是有点不同的吧。因为运行在 HPC 上的程序大多依赖 MPI 做并行计算,网络应该是主要的 jitter 来源,不过也许可以看看对于单个 server 的 os jitter 吗? 有什么推荐的关键词吗? 如果我想尽量避免 OS 带来的影响,目前最轻的 Linux 发行版是什么? |
83
ryd994 2020-07-19 08:15:46 +08:00 1
@vcfghtyjc 就是我上面说的。就算你不用,操作系统编译时有相应的支持,就可能有相关的后台动作,比如可能时不时的要去检查一下网卡。
hpc 上单机的 jitter 会拖慢整个集群,因为大家都在等最慢的那个同步。节点数量多了以后,小概率也变成大概率,至少有一个节点是慢的。于是整个集群就废了。 你现在就有可能是 jitter 的影响,只不过单机影响没那么大而已。 |
86
hailinzeng 2020-07-19 09:55:31 +08:00
![different levels of approx. access times]( https://i.stack.imgur.com/xVhVi.png)
|
87
reus 2020-07-19 09:58:44 +08:00
@vcfghtyjc linux 内核本身就有实时选项,直接编译即可,不用魔改。但是具体能做到多实时,对你的场景有没有影响,还要具体试过才知道。
我很好奇为啥你要做这种程度的测量,却又不用 C 类可以精细控制内存的语言? |
88
hailinzeng 2020-07-19 10:14:25 +08:00
L1/2 Cache 1ns
L3 Cache 10ns Main Memory 100ns SATA SSDs 100,000ns HDD 5,000,000ns https://stackoverflow.com/a/42435902 |
91
dalabenba 2020-07-19 10:57:22 +08:00 via Android
@vcfghtyjc 我觉得这个在考虑到 cache 之前应该先考虑下 io (比如读取程序的 pagecache )造成的差异,你可以每次 bench 时候打一下火焰图,定位下函数的差异
|
92
peihanw 2020-07-19 11:13:28 +08:00
系统 BIOS 里可以禁用“DRAM Prefetch”、“CPU Core Hardware Prefetcher”、“CPU Cache Stride Prefetcher”(不同主板 BIOS 设置可能有些差异),楼主可以分别 /组合试试。对特定程序(xmrig 那类你懂的)性能会有所提升。虚拟机 /云主机都不行的,只能物理机。
|
93
reus 2020-07-19 11:26:43 +08:00 via Android
@vcfghtyjc 那没意义,go 运行时本身就做了很多事情,gc,调度都会带来额外的延迟和抖动,根本轮不到操作系统甚至 cpu 层面。建议放弃这个方向。
|
94
Aalen 2020-07-19 11:57:04 +08:00
hmmm 以前在 bios 能关缓存,依稀记得我之前有一块奔腾 4,就是二级缓存坏了,bios 关掉 cache 可以用,打开 cache Windows 蓝屏
|
95
vcfghtyjc OP @reus 但是我用 KNN 确实见到了分层,现在不是很确定是否因为 locality 。是否有办法可以检测 Golang 带来的抖动?
|
96
reus 2020-07-19 12:13:24 +08:00
|
97
vcfghtyjc OP @dalabenba 每次测的都是同一个 function,程序本身并不大,应该不会因为 disk IO 带来差异吧?还是说我对 IO 的理解有问题?
|
99
jsteward 2020-07-19 13:02:03 +08:00
@imbushuo datapath 和對應的 latency 都在,不過 cacheline 不會 refill,也就是每次都 miss,效果上除了會比 dedicated datapath 稍慢,跟沒有沒有區別啦。
|
100
Gwzlchn 2020-07-19 14:48:21 +08:00
这个和我本科毕设有点像,我当时有一部分工作测量的是每条指令在太湖之光的 CPU 周期数。当然最后我也没做明白就是了。
先说一下,神威平台是两级 cache,L1 分 data cache 和 ins cache 、L2 不区分。指令集就有点像 MIPS (实际是 Alpha 指令集) 访存指令比较简单了,我当时也考虑了 CPU cache 的问题,那你两条 load/store 指令之间访问数据的距离要大于一整个 L2 cache 的大小就可以了。 最坑爹的是 add/div 之类的计算指令,这个我现在也没想出来应该怎么准确测量出来,因为现在的高级处理器都是多发射+多级流水线的。两个指令之间实际上就差一个最后的写回阶段的间隔。 这个消除流水线+多发射的影响楼主有啥好一点的思路吗? |