通过施加内存压力来减慢 CPU 频率
Slowing down CPU Frequency by imposing memory stress
我对我的系统进行了压力,以了解它如何影响我使用 stress-ng 编写的某些程序。
程序本身是一个神经网络,主要由一些嵌套循环组成,执行一些乘法运算,并使用大约 1G 的 RAM 整体用 C++ 编码。
我使用以下方法对系统施加了一些内存压力:
stress-ng --vm 4 --vm-bytes 2G -t 100s
这会创建 4 个在 mmap 上旋转的工作人员,每个工作人员分配 2G RAM。这显着减慢了我的程序的执行速度(从大约 150 毫秒到 250 毫秒)。但是程序变慢的原因不是内存不足或内存带宽不足或其他原因。相反,CPU 周期从 3.4GHz(没有压力-ng)减少到 2.8GHz(有压力-ng)。 CPU 利用率与预期保持大致相同 (99%)。
我使用
测量了 CPU 频率
sudo perf stat -B ./my_program
有人知道为什么内存压力会减慢 CPU 吗?
我的 CPU 是 Intel(R) Core(TM) i5-8250U 我的 OS 是 Ubuntu 18.04.
亲切的问候lpolari
重要的是要记住现代 CPUs,尤其是 Intel 制造的那些,具有可变的时钟频率。 CPU 会在轻载时缓慢 运行 以节省电量,从而延长电池寿命,但会在负载下逐渐增加。
限制因素是热量,即 CPU 只允许在调整频率以降低功耗之前变得如此热,并推而广之, 发热.
在具有多个内核的芯片上,单个内核可以 运行 非常快而不会达到热节流。两个核心必须 运行 变慢,它们有效地产生两倍的热量,并且当使用所有四个核心时,每个核心都必须分担整个热预算的一小部分。
值得检查一下你的 CPU 体温,因为测试 运行ning 因为它可能会达到某种上限。
Skylake-derived CPUs 在负载/存储瓶颈时确实会降低其核心时钟速度,在有利于更省电的能源与性能设置下。令人惊讶的是,您可以构建人为的情况,其中即使所有存储都命中 L1d 缓存或从未初始化的内存加载(仍然 CoW 映射到相同的零页)也会发生这种降频。
Skylake 引入了对 CPU 频率的完全硬件控制(硬件 P-state = HWP)。 https://unix.stackexchange.com/questions/439340/what-are-the-implications-of-setting-the-cpu-governor-to-performance 频率决定可以考虑到内部 performance-monitoring ,它可以注意到诸如花费大多数周期停滞或停滞的原因之类的事情。我不知道 Skylake 究竟使用什么启发式算法。
您可以通过遍历大型数组而不进行任何系统调用来重现此1。如果它很大(或者您在人工测试中跨越缓存行),perf stat ./a.out
将显示平均时钟速度低于正常 CPU-bound 循环。
理论上,如果内存完全跟不上 CPU,降低核心时钟速度(并保持内存控制器不变)不会对性能造成太大影响。实际上,降低时钟速度也会降低非核心时钟速度(环形总线 + L3 缓存),内存延迟和带宽也会有所恶化。
缓存未命中的部分延迟是将请求从 CPU 核心获取到内存控制器,并且 single-core 带宽受限于最大并发数(一个核心可以跟踪的未完成请求) / 潜伏。
例如我的 i7-6700k 从 3.9GHz 下降到 2.7GHz 当 运行 设置一个微基准测试时,该基准测试仅在默认启动设置下出现 DRAM 瓶颈。 (此外,它只达到 3.9GHz 而不是 4.0 all-core 或 4.2GHz,1 或 2 个内核在 BIOS 中配置为活动,默认 balance_power
EPP 设置在启动时或 balance_performance
.)
这个默认值似乎不太好,对于“客户端”芯片来说太保守了,在“客户端”芯片中,单核几乎可以使 DRAM 带宽饱和,但只能以全时钟速度运行。或者对节能过于激进,如果你从另一个 POV 来看,特别是对于像我的桌面这样具有高 TDP (95W) 的芯片,即使在 运行ning power-hungry 东西时也可以无限期地维持全时钟速度比如大量使用 AVX2 的 x265 视频编码。
使用像 i5-8250U 这样的 ULV 15W 芯片可能更有意义,以便在 CPU 做某事时尝试留出更多的热/功率余量更有趣。
这取决于他们的能源/性能偏好 (EPP) 设置。它在默认 balance_power
设置下发生得相当强烈。它根本不会完全 performance
发生,一些快速基准测试表明 balance_performance
也避免了这种节能减慢。我在桌面上使用 balance_performance
。
“客户端”(non-Xeon)Ice Lake 之前的芯片将所有内核锁定在一起,因此它们 运行 具有相同的时钟速度(并且即使其中之一也会 运行 更高它们是 运行ning 一些不受内存限制的东西,比如 while(1) { _mm_pause(); }
循环)。但是每个逻辑核心仍然有一个 EPP 设置。我一直只是更改所有内核的设置以保持它们相同:
在 Linux 上,读取设置:
$ grep . /sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference
/sys/devices/system/cpu/cpufreq/policy0/energy_performance_preference:balance_performance
/sys/devices/system/cpu/cpufreq/policy1/energy_performance_preference:balance_performance
...
/sys/devices/system/cpu/cpufreq/policy7/energy_performance_preference:balance_performance
写入设置:
sudo sh -c 'for i in /sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference;
do echo balance_performance > "$i"; done'
另见
x86_energy_perf_policy(8)
手册页
- Linux Intel Performance and Energy Bias Hint
的内核文档
脚注1:实验示例:
每个缓存行存储 1 个双字,通过连续的缓存行前进直到缓冲区末尾,然后将指针返回到开头。无论缓冲区大小如何,对固定数量的存储重复。
;; t=testloop; nasm -felf64 "$t.asm" && ld "$t.o" -o "$t" && taskset -c 3 perf stat -d -etask-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,uops_issued.any,uops_executed.thread ./"$t"
;; nasm -felf64 testloop.asm
;; ld -o testloop testloop.o
;; taskset -c 3 perf stat -etask-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,uops_issued.any,uops_executed.thread -r1 ./testloop
; or idq.mite_uops
default rel
%ifdef __YASM_VER__
; CPU intelnop
; CPU Conroe AMD
CPU Skylake AMD
%else
%use smartalign
alignmode p6, 64
%endif
global _start
_start:
lea rdi, [buf]
lea rsi, [endbuf]
; mov rsi, qword endbuf ; large buffer. NASM / YASM can't actually handle a huge BSS and hit a failed assert (NASM) or make a binary that doesn't reserve enough BSS space.
mov ebp, 1000000000
align 64
.loop:
%if 0
mov eax, [rdi] ; LOAD
mov eax, [rdi+64]
%else
mov [rdi], eax ; STORE
mov [rdi+64], eax
%endif
add rdi, 128
cmp rdi, rsi
jae .wrap_ptr ; normally falls through, total loop = 4 fused-domain uops
.back:
dec ebp
jnz .loop
.end:
xor edi,edi
mov eax,231 ; __NR_exit_group from /usr/include/asm/unistd_64.h
syscall ; sys_exit_group(0)
.wrap_ptr:
lea rdi, [buf]
jmp .back
section .bss
align 4096
;buf: resb 2048*1024*1024 - 1024*1024 ; just under 2GiB so RIP-rel still works
buf: resb 1024*1024 / 64 ; 16kiB = half of L1d
endbuf:
resb 4096 ; spare space to allow overshoot
测试系统:Arch GNU/Linux,内核5.7.6-arch1-1。 (以及来自 GNU Binutils 2.34.0 的 NASM 2.14.02,ld
)。
- CPU:i7-6700k 天湖
- 主板:Asus Z170 Pro Gaming,在 BIOS 中配置为 1 或 2 核 Turbo = 4.2GHz,3 或 4 核 = 4.0GHz。但是启动时默认的 EPP 设置是
balance_power
,它只能达到 3.9GHz。我的启动脚本更改为 balance_pwerformance
,它仍然只达到 3.9GHz,因此风扇保持安静,但不那么保守。
- DRAM:DDR4-2666(与没有缓存未命中的小测试无关)。
超线程已启用,但系统处于空闲状态并且内核不会在另一个逻辑内核(我将其固定到的同级内核)上安排任何内容,因此它有一个物理内核。
然而,这意味着 perf 不愿意为一个线程使用更多的可编程性能计数器,因此 perf stat -d
来监视 L1d 负载和替换,而 L3 命中/未命中将意味着对 cycles
等等。它可以忽略不计,比如 424k L1-dcache-loads(可能在内核 page-fault 处理程序、中断处理程序和其他开销中,因为循环没有负载)。 L1-dcache-load-misses
实际上是 L1D.REPLACEMENT
甚至更低,比如 48k
我使用了一些 perf 事件,包括 exe_activity.bound_on_stores
-[存储缓冲区已满且没有突出显示的循环g负载]。 (有关说明,请参阅 perf list
,有关更多信息,请参阅 and/or 英特尔手册)。
EPP:balance_power
:从 3.9GHz 降频到 2.7GHz
EPP 设置:balance_power
和 sudo sh -c 'for i in /sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference;do echo balance_power > "$i";done'
节流是基于代码的行为;在另一个保持高时钟的核心上有一个暂停循环,这将 运行 在此代码上更快。或者在循环中使用不同的指令。
# sudo ... balance_power
$ taskset -c 3 perf stat -etask-clock:u,task-clock,context-switches,cpu-migrations,page-faults,cycles,branches,instructions,uops_issued.any,uops_executed.thread,exe_activity.bound_on_stores -r1 ./"$t"
Performance counter stats for './testloop':
779.56 msec task-clock:u # 1.000 CPUs utilized
779.56 msec task-clock # 1.000 CPUs utilized
3 context-switches # 0.004 K/sec
0 cpu-migrations # 0.000 K/sec
6 page-faults # 0.008 K/sec
2,104,778,670 cycles # 2.700 GHz
2,008,110,142 branches # 2575.962 M/sec
7,017,137,958 instructions # 3.33 insn per cycle
5,217,161,206 uops_issued.any # 6692.465 M/sec
7,191,265,987 uops_executed.thread # 9224.805 M/sec
613,076,394 exe_activity.bound_on_stores # 786.442 M/sec
0.779907034 seconds time elapsed
0.779451000 seconds user
0.000000000 seconds sys
巧合的是,这恰好达到了 2.7GHz。通常会有一些噪音或启动开销,而且会低一些。请注意,5217951928 front-end uops / 2106180524 cycles = 每个周期发出的平均 uops ~2.48,流水线宽度为 4,因此这不是 low-throughput 代码。由于 macro-fused compare/branch,指令数更高。 (我本可以展开更多,所以更多的指令是存储,更少的添加和分支,但我没有。)
(我 re-ran perf stat
命令几次所以 CPU 不只是在定时间隔开始时从 low-power 睡眠中醒来。有仍然是间隔内的页面错误,但 6 个页面错误在 3/4 秒的基准测试中可以忽略不计。)
balance_performance
:全 3.9GHz,此 EPP 的最高速度
没有基于代码正在做什么的限制。
# sudo ... balance_performance
$ taskset -c 3 perf stat -etask-clock:u,task-clock,context-switches,cpu-migrations,page-faults,cycles,branches,instructions,uops_issued.any,uops_executed.thread,exe_activity.bound_on_stores -r1 ./"$t"
Performance counter stats for './testloop':
539.83 msec task-clock:u # 0.999 CPUs utilized
539.83 msec task-clock # 0.999 CPUs utilized
3 context-switches # 0.006 K/sec
0 cpu-migrations # 0.000 K/sec
6 page-faults # 0.011 K/sec
2,105,328,671 cycles # 3.900 GHz
2,008,030,096 branches # 3719.713 M/sec
7,016,729,050 instructions # 3.33 insn per cycle
5,217,686,004 uops_issued.any # 9665.340 M/sec
7,192,389,444 uops_executed.thread # 13323.318 M/sec
626,115,041 exe_activity.bound_on_stores # 1159.827 M/sec
0.540108507 seconds time elapsed
0.539877000 seconds user
0.000000000 seconds sys
在 clock-for-clock 的基础上大致相同,尽管存储缓冲区已满的总周期略多。 (这是在核心和 L1d 缓存之间,而不是在核心之外,所以我们期望循环本身大致相同。使用 -r10
重复 10 次,该数字在 [=163= 中稳定 +- 0.01% ]s.)
performance
:4.2GHz,全睿频至最高配置频率
没有基于代码正在做什么的限制。
# sudo ... performance
taskset -c 3 perf stat -etask-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,uops_issued.any,uops_executed.thread -r1 ./testloop
Performance counter stats for './testloop':
500.95 msec task-clock:u # 1.000 CPUs utilized
500.95 msec task-clock # 1.000 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
7 page-faults # 0.014 K/sec
2,098,112,999 cycles # 4.188 GHz
2,007,994,492 branches # 4008.380 M/sec
7,016,551,461 instructions # 3.34 insn per cycle
5,217,839,192 uops_issued.any # 10415.906 M/sec
7,192,116,174 uops_executed.thread # 14356.978 M/sec
624,662,664 exe_activity.bound_on_stores # 1246.958 M/sec
0.501151045 seconds time elapsed
0.501042000 seconds user
0.000000000 seconds sys
整体性能与时钟速度呈线性关系,因此与 balance_power
相比,这是约 1.5 倍的加速。 (balance_performance
为 1.44,具有相同的 3.9GHz 全时钟速度。)
对于大到足以导致 L1d 或 L2 缓存未命中的缓冲区,核心时钟周期仍然存在差异。
我上次查看它时,它启用了允许处理器执行此操作的“energy-efficient Turbo”设置。粗略地说,硬件会监控每个周期的指令,如果增加的频率没有导致足够的吞吐量增加,则不会继续增加 Turbo 频率。对于 STREAM 基准测试,频率通常会下降几个 bin,但性能在渐近性能的 1% 以内。
我不知道英特尔是否记录了“Energy Efficient Turbo”设置如何与“Energy-Performance Preference”的所有各种风格相互作用。在我们的生产系统中,“Energy Efficient Turbo”在 BIOS 中被禁用,但它有时默认启用....
我对我的系统进行了压力,以了解它如何影响我使用 stress-ng 编写的某些程序。
程序本身是一个神经网络,主要由一些嵌套循环组成,执行一些乘法运算,并使用大约 1G 的 RAM 整体用 C++ 编码。
我使用以下方法对系统施加了一些内存压力:
stress-ng --vm 4 --vm-bytes 2G -t 100s
这会创建 4 个在 mmap 上旋转的工作人员,每个工作人员分配 2G RAM。这显着减慢了我的程序的执行速度(从大约 150 毫秒到 250 毫秒)。但是程序变慢的原因不是内存不足或内存带宽不足或其他原因。相反,CPU 周期从 3.4GHz(没有压力-ng)减少到 2.8GHz(有压力-ng)。 CPU 利用率与预期保持大致相同 (99%)。
我使用
测量了 CPU 频率sudo perf stat -B ./my_program
有人知道为什么内存压力会减慢 CPU 吗?
我的 CPU 是 Intel(R) Core(TM) i5-8250U 我的 OS 是 Ubuntu 18.04.
亲切的问候lpolari
重要的是要记住现代 CPUs,尤其是 Intel 制造的那些,具有可变的时钟频率。 CPU 会在轻载时缓慢 运行 以节省电量,从而延长电池寿命,但会在负载下逐渐增加。
限制因素是热量,即 CPU 只允许在调整频率以降低功耗之前变得如此热,并推而广之, 发热.
在具有多个内核的芯片上,单个内核可以 运行 非常快而不会达到热节流。两个核心必须 运行 变慢,它们有效地产生两倍的热量,并且当使用所有四个核心时,每个核心都必须分担整个热预算的一小部分。
值得检查一下你的 CPU 体温,因为测试 运行ning 因为它可能会达到某种上限。
Skylake-derived CPUs 在负载/存储瓶颈时确实会降低其核心时钟速度,在有利于更省电的能源与性能设置下。令人惊讶的是,您可以构建人为的情况,其中即使所有存储都命中 L1d 缓存或从未初始化的内存加载(仍然 CoW 映射到相同的零页)也会发生这种降频。
Skylake 引入了对 CPU 频率的完全硬件控制(硬件 P-state = HWP)。 https://unix.stackexchange.com/questions/439340/what-are-the-implications-of-setting-the-cpu-governor-to-performance 频率决定可以考虑到内部 performance-monitoring ,它可以注意到诸如花费大多数周期停滞或停滞的原因之类的事情。我不知道 Skylake 究竟使用什么启发式算法。
您可以通过遍历大型数组而不进行任何系统调用来重现此1。如果它很大(或者您在人工测试中跨越缓存行),perf stat ./a.out
将显示平均时钟速度低于正常 CPU-bound 循环。
理论上,如果内存完全跟不上 CPU,降低核心时钟速度(并保持内存控制器不变)不会对性能造成太大影响。实际上,降低时钟速度也会降低非核心时钟速度(环形总线 + L3 缓存),内存延迟和带宽也会有所恶化。
缓存未命中的部分延迟是将请求从 CPU 核心获取到内存控制器,并且 single-core 带宽受限于最大并发数(一个核心可以跟踪的未完成请求) / 潜伏。
例如我的 i7-6700k 从 3.9GHz 下降到 2.7GHz 当 运行 设置一个微基准测试时,该基准测试仅在默认启动设置下出现 DRAM 瓶颈。 (此外,它只达到 3.9GHz 而不是 4.0 all-core 或 4.2GHz,1 或 2 个内核在 BIOS 中配置为活动,默认 balance_power
EPP 设置在启动时或 balance_performance
.)
这个默认值似乎不太好,对于“客户端”芯片来说太保守了,在“客户端”芯片中,单核几乎可以使 DRAM 带宽饱和,但只能以全时钟速度运行。或者对节能过于激进,如果你从另一个 POV 来看,特别是对于像我的桌面这样具有高 TDP (95W) 的芯片,即使在 运行ning power-hungry 东西时也可以无限期地维持全时钟速度比如大量使用 AVX2 的 x265 视频编码。
使用像 i5-8250U 这样的 ULV 15W 芯片可能更有意义,以便在 CPU 做某事时尝试留出更多的热/功率余量更有趣。
这取决于他们的能源/性能偏好 (EPP) 设置。它在默认 balance_power
设置下发生得相当强烈。它根本不会完全 performance
发生,一些快速基准测试表明 balance_performance
也避免了这种节能减慢。我在桌面上使用 balance_performance
。
“客户端”(non-Xeon)Ice Lake 之前的芯片将所有内核锁定在一起,因此它们 运行 具有相同的时钟速度(并且即使其中之一也会 运行 更高它们是 运行ning 一些不受内存限制的东西,比如 while(1) { _mm_pause(); }
循环)。但是每个逻辑核心仍然有一个 EPP 设置。我一直只是更改所有内核的设置以保持它们相同:
在 Linux 上,读取设置:
$ grep . /sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference
/sys/devices/system/cpu/cpufreq/policy0/energy_performance_preference:balance_performance
/sys/devices/system/cpu/cpufreq/policy1/energy_performance_preference:balance_performance
...
/sys/devices/system/cpu/cpufreq/policy7/energy_performance_preference:balance_performance
写入设置:
sudo sh -c 'for i in /sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference;
do echo balance_performance > "$i"; done'
另见
x86_energy_perf_policy(8)
手册页- Linux Intel Performance and Energy Bias Hint 的内核文档
脚注1:实验示例:
每个缓存行存储 1 个双字,通过连续的缓存行前进直到缓冲区末尾,然后将指针返回到开头。无论缓冲区大小如何,对固定数量的存储重复。
;; t=testloop; nasm -felf64 "$t.asm" && ld "$t.o" -o "$t" && taskset -c 3 perf stat -d -etask-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,uops_issued.any,uops_executed.thread ./"$t"
;; nasm -felf64 testloop.asm
;; ld -o testloop testloop.o
;; taskset -c 3 perf stat -etask-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,uops_issued.any,uops_executed.thread -r1 ./testloop
; or idq.mite_uops
default rel
%ifdef __YASM_VER__
; CPU intelnop
; CPU Conroe AMD
CPU Skylake AMD
%else
%use smartalign
alignmode p6, 64
%endif
global _start
_start:
lea rdi, [buf]
lea rsi, [endbuf]
; mov rsi, qword endbuf ; large buffer. NASM / YASM can't actually handle a huge BSS and hit a failed assert (NASM) or make a binary that doesn't reserve enough BSS space.
mov ebp, 1000000000
align 64
.loop:
%if 0
mov eax, [rdi] ; LOAD
mov eax, [rdi+64]
%else
mov [rdi], eax ; STORE
mov [rdi+64], eax
%endif
add rdi, 128
cmp rdi, rsi
jae .wrap_ptr ; normally falls through, total loop = 4 fused-domain uops
.back:
dec ebp
jnz .loop
.end:
xor edi,edi
mov eax,231 ; __NR_exit_group from /usr/include/asm/unistd_64.h
syscall ; sys_exit_group(0)
.wrap_ptr:
lea rdi, [buf]
jmp .back
section .bss
align 4096
;buf: resb 2048*1024*1024 - 1024*1024 ; just under 2GiB so RIP-rel still works
buf: resb 1024*1024 / 64 ; 16kiB = half of L1d
endbuf:
resb 4096 ; spare space to allow overshoot
测试系统:Arch GNU/Linux,内核5.7.6-arch1-1。 (以及来自 GNU Binutils 2.34.0 的 NASM 2.14.02,ld
)。
- CPU:i7-6700k 天湖
- 主板:Asus Z170 Pro Gaming,在 BIOS 中配置为 1 或 2 核 Turbo = 4.2GHz,3 或 4 核 = 4.0GHz。但是启动时默认的 EPP 设置是
balance_power
,它只能达到 3.9GHz。我的启动脚本更改为balance_pwerformance
,它仍然只达到 3.9GHz,因此风扇保持安静,但不那么保守。 - DRAM:DDR4-2666(与没有缓存未命中的小测试无关)。
超线程已启用,但系统处于空闲状态并且内核不会在另一个逻辑内核(我将其固定到的同级内核)上安排任何内容,因此它有一个物理内核。
然而,这意味着 perf 不愿意为一个线程使用更多的可编程性能计数器,因此 perf stat -d
来监视 L1d 负载和替换,而 L3 命中/未命中将意味着对 cycles
等等。它可以忽略不计,比如 424k L1-dcache-loads(可能在内核 page-fault 处理程序、中断处理程序和其他开销中,因为循环没有负载)。 L1-dcache-load-misses
实际上是 L1D.REPLACEMENT
甚至更低,比如 48k
我使用了一些 perf 事件,包括 exe_activity.bound_on_stores
-[存储缓冲区已满且没有突出显示的循环g负载]。 (有关说明,请参阅 perf list
,有关更多信息,请参阅 and/or 英特尔手册)。
EPP:balance_power
:从 3.9GHz 降频到 2.7GHz
EPP 设置:balance_power
和 sudo sh -c 'for i in /sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference;do echo balance_power > "$i";done'
节流是基于代码的行为;在另一个保持高时钟的核心上有一个暂停循环,这将 运行 在此代码上更快。或者在循环中使用不同的指令。
# sudo ... balance_power
$ taskset -c 3 perf stat -etask-clock:u,task-clock,context-switches,cpu-migrations,page-faults,cycles,branches,instructions,uops_issued.any,uops_executed.thread,exe_activity.bound_on_stores -r1 ./"$t"
Performance counter stats for './testloop':
779.56 msec task-clock:u # 1.000 CPUs utilized
779.56 msec task-clock # 1.000 CPUs utilized
3 context-switches # 0.004 K/sec
0 cpu-migrations # 0.000 K/sec
6 page-faults # 0.008 K/sec
2,104,778,670 cycles # 2.700 GHz
2,008,110,142 branches # 2575.962 M/sec
7,017,137,958 instructions # 3.33 insn per cycle
5,217,161,206 uops_issued.any # 6692.465 M/sec
7,191,265,987 uops_executed.thread # 9224.805 M/sec
613,076,394 exe_activity.bound_on_stores # 786.442 M/sec
0.779907034 seconds time elapsed
0.779451000 seconds user
0.000000000 seconds sys
巧合的是,这恰好达到了 2.7GHz。通常会有一些噪音或启动开销,而且会低一些。请注意,5217951928 front-end uops / 2106180524 cycles = 每个周期发出的平均 uops ~2.48,流水线宽度为 4,因此这不是 low-throughput 代码。由于 macro-fused compare/branch,指令数更高。 (我本可以展开更多,所以更多的指令是存储,更少的添加和分支,但我没有。)
(我 re-ran perf stat
命令几次所以 CPU 不只是在定时间隔开始时从 low-power 睡眠中醒来。有仍然是间隔内的页面错误,但 6 个页面错误在 3/4 秒的基准测试中可以忽略不计。)
balance_performance
:全 3.9GHz,此 EPP 的最高速度
没有基于代码正在做什么的限制。
# sudo ... balance_performance
$ taskset -c 3 perf stat -etask-clock:u,task-clock,context-switches,cpu-migrations,page-faults,cycles,branches,instructions,uops_issued.any,uops_executed.thread,exe_activity.bound_on_stores -r1 ./"$t"
Performance counter stats for './testloop':
539.83 msec task-clock:u # 0.999 CPUs utilized
539.83 msec task-clock # 0.999 CPUs utilized
3 context-switches # 0.006 K/sec
0 cpu-migrations # 0.000 K/sec
6 page-faults # 0.011 K/sec
2,105,328,671 cycles # 3.900 GHz
2,008,030,096 branches # 3719.713 M/sec
7,016,729,050 instructions # 3.33 insn per cycle
5,217,686,004 uops_issued.any # 9665.340 M/sec
7,192,389,444 uops_executed.thread # 13323.318 M/sec
626,115,041 exe_activity.bound_on_stores # 1159.827 M/sec
0.540108507 seconds time elapsed
0.539877000 seconds user
0.000000000 seconds sys
在 clock-for-clock 的基础上大致相同,尽管存储缓冲区已满的总周期略多。 (这是在核心和 L1d 缓存之间,而不是在核心之外,所以我们期望循环本身大致相同。使用 -r10
重复 10 次,该数字在 [=163= 中稳定 +- 0.01% ]s.)
performance
:4.2GHz,全睿频至最高配置频率
没有基于代码正在做什么的限制。
# sudo ... performance
taskset -c 3 perf stat -etask-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,uops_issued.any,uops_executed.thread -r1 ./testloop
Performance counter stats for './testloop':
500.95 msec task-clock:u # 1.000 CPUs utilized
500.95 msec task-clock # 1.000 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
7 page-faults # 0.014 K/sec
2,098,112,999 cycles # 4.188 GHz
2,007,994,492 branches # 4008.380 M/sec
7,016,551,461 instructions # 3.34 insn per cycle
5,217,839,192 uops_issued.any # 10415.906 M/sec
7,192,116,174 uops_executed.thread # 14356.978 M/sec
624,662,664 exe_activity.bound_on_stores # 1246.958 M/sec
0.501151045 seconds time elapsed
0.501042000 seconds user
0.000000000 seconds sys
整体性能与时钟速度呈线性关系,因此与 balance_power
相比,这是约 1.5 倍的加速。 (balance_performance
为 1.44,具有相同的 3.9GHz 全时钟速度。)
对于大到足以导致 L1d 或 L2 缓存未命中的缓冲区,核心时钟周期仍然存在差异。
我上次查看它时,它启用了允许处理器执行此操作的“energy-efficient Turbo”设置。粗略地说,硬件会监控每个周期的指令,如果增加的频率没有导致足够的吞吐量增加,则不会继续增加 Turbo 频率。对于 STREAM 基准测试,频率通常会下降几个 bin,但性能在渐近性能的 1% 以内。
我不知道英特尔是否记录了“Energy Efficient Turbo”设置如何与“Energy-Performance Preference”的所有各种风格相互作用。在我们的生产系统中,“Energy Efficient Turbo”在 BIOS 中被禁用,但它有时默认启用....