运行 时间和在 linux perf 中报告的周期计数
Run time and reported cycle counts in linux perf
我在 4 核 Intel CPU(每个内核 1 个线程)上有 运行 单线程矩阵乘法,但是 perf 的数字没有意义。
Performance counter stats for 'system wide':
31,728,397,287 cpu-cycles # 0.462 GHz
131,661,730,104 ref-cycles # 1916.425 M/sec
68,701.58 msec cpu-clock # 4.000 CPUs utilized
68,701.90 msec task-clock # 4.000 CPUs utilized
31,728,553,882 cpu/cpu-cycles/ # 461.830 M/sec
17.176244725 seconds time elapsed
我已将 cpu 频率设置为最低并观察它,所有内核都 运行 以 800MHz 运行。这意味着 1 个周期为 1.25ns。总 cpu 周期 31,728,397,287 执行时间应为 39.66 秒,但 运行 时间为 17.1 秒。
我也不知道为什么0.462GHz写在cpu-cycles前面
有关处理器的更多信息:
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 94
Model name: Intel(R) Core(TM) i5-6600 CPU @ 3.30GHz
Stepping: 3
CPU MHz: 800.022
CPU max MHz: 3900,0000
CPU min MHz: 800,0000
有什么想法吗?
更新:
我重新运行 root 权限和指定用户代码的实验。
# perf stat -a -e cycles:u,cycles,cpu-clock ./mm_double_omp 1
Using 1 threads
Total execution Time in seconds: 15.4839418610
MM execution Time in seconds: 15.3758427450
Performance counter stats for 'system wide':
14,237,521,876 cycles:u # 0.230 GHz
17,470,220,108 cycles # 0.282 GHz
61,974.41 msec cpu-clock # 4.000 CPUs utilized
15.494002570 seconds time elapsed
如您所见,频率仍然不是 800MHz。但是,如果我不指定 -a
结果是有意义的,因为 cycles:u * (1/800MHz) 几乎与经过的时间相同。
# perf stat -e cycles:u,cycles,cpu-clock ./mm_double_omp 1
Using 1 threads
Total execution Time in seconds: 16.5347361100
MM execution Time in seconds: 16.4267430900
Performance counter stats for './mm_double_omp 1':
13.135.516.694 cycles:u # 0,794 GHz
13.201.778.987 cycles # 0,798 GHz
16.541,22 msec cpu-clock # 1,000 CPUs utilized
16,544487905 seconds time elapsed
16,522146000 seconds user
0,019997000 seconds sys
I have run a single thread matrix multiplication
但是当 运行ning 时,您计算了所有 4 个内核的 system-wide。 这就是 perf -a
所做的,以及为什么你的输出中有 Performance counter stats for 'system wide':
。
因此内核的 task-clock
“事件”在您的进程处于活动状态时计算所有 4 个内核的时间:
68,701.90 msec task-clock # 4.000 CPUs utilized
那是 68.7 CPU-seconds,几乎正好是 4x 17.17 秒,这是有道理的。
I also don't know why 0.462 GHz is written in front of cpu-cycles.
这是您的代码处于活动状态期间所有 4 个内核的平均值 cycles/time。 CPU 处于睡眠状态的时钟不会滴答作响,因此在您的代码保持 1 个核心忙碌期间,平均负载似乎是 4 * 462/800 = 2.31
CPU 没有处于睡眠状态。
因此,当您的系统平均 运行 运行另外 1.3 个线程时,您正在执行基准测试。 (包括 CPU 中断唤醒时间)
我假设您的测量值不限于 user-space-only(不包括在内核模式下花费的滴答声);这是另一种可能的影响。
如果您没有使用 -a
,如果您只计算 user-space 个周期,而不是花费在核心。 (例如 perf stat --all-user
,或者你的 kernel.perf_event_paranoid
设置足够高,不允许你在内核中分析硬件事件,这有效地将 :u
应用于硬件事件,但不会将它们打印为 cycles:u
.)
如果您将 kernel.perf_event_paranoid
sysctl 设置更改为 0,或 运行 perf
作为 root,您应该看到 800 MHz 作为周期 / task-clock,因为那是CPU 的速度是 运行ning 而你的线程是 运行ning.
不在 user-space 中花费大量周期表明您的代码在内核中花费了大量时间,如果您使用大数组,可能会处理页面错误。
我在 4 核 Intel CPU(每个内核 1 个线程)上有 运行 单线程矩阵乘法,但是 perf 的数字没有意义。
Performance counter stats for 'system wide':
31,728,397,287 cpu-cycles # 0.462 GHz
131,661,730,104 ref-cycles # 1916.425 M/sec
68,701.58 msec cpu-clock # 4.000 CPUs utilized
68,701.90 msec task-clock # 4.000 CPUs utilized
31,728,553,882 cpu/cpu-cycles/ # 461.830 M/sec
17.176244725 seconds time elapsed
我已将 cpu 频率设置为最低并观察它,所有内核都 运行 以 800MHz 运行。这意味着 1 个周期为 1.25ns。总 cpu 周期 31,728,397,287 执行时间应为 39.66 秒,但 运行 时间为 17.1 秒。
我也不知道为什么0.462GHz写在cpu-cycles前面
有关处理器的更多信息:
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 94
Model name: Intel(R) Core(TM) i5-6600 CPU @ 3.30GHz
Stepping: 3
CPU MHz: 800.022
CPU max MHz: 3900,0000
CPU min MHz: 800,0000
有什么想法吗?
更新:
我重新运行 root 权限和指定用户代码的实验。
# perf stat -a -e cycles:u,cycles,cpu-clock ./mm_double_omp 1
Using 1 threads
Total execution Time in seconds: 15.4839418610
MM execution Time in seconds: 15.3758427450
Performance counter stats for 'system wide':
14,237,521,876 cycles:u # 0.230 GHz
17,470,220,108 cycles # 0.282 GHz
61,974.41 msec cpu-clock # 4.000 CPUs utilized
15.494002570 seconds time elapsed
如您所见,频率仍然不是 800MHz。但是,如果我不指定 -a
结果是有意义的,因为 cycles:u * (1/800MHz) 几乎与经过的时间相同。
# perf stat -e cycles:u,cycles,cpu-clock ./mm_double_omp 1
Using 1 threads
Total execution Time in seconds: 16.5347361100
MM execution Time in seconds: 16.4267430900
Performance counter stats for './mm_double_omp 1':
13.135.516.694 cycles:u # 0,794 GHz
13.201.778.987 cycles # 0,798 GHz
16.541,22 msec cpu-clock # 1,000 CPUs utilized
16,544487905 seconds time elapsed
16,522146000 seconds user
0,019997000 seconds sys
I have run a single thread matrix multiplication
但是当 运行ning 时,您计算了所有 4 个内核的 system-wide。 这就是 perf -a
所做的,以及为什么你的输出中有 Performance counter stats for 'system wide':
。
因此内核的 task-clock
“事件”在您的进程处于活动状态时计算所有 4 个内核的时间:
68,701.90 msec task-clock # 4.000 CPUs utilized
那是 68.7 CPU-seconds,几乎正好是 4x 17.17 秒,这是有道理的。
I also don't know why 0.462 GHz is written in front of cpu-cycles.
这是您的代码处于活动状态期间所有 4 个内核的平均值 cycles/time。 CPU 处于睡眠状态的时钟不会滴答作响,因此在您的代码保持 1 个核心忙碌期间,平均负载似乎是 4 * 462/800 = 2.31
CPU 没有处于睡眠状态。
因此,当您的系统平均 运行 运行另外 1.3 个线程时,您正在执行基准测试。 (包括 CPU 中断唤醒时间)
我假设您的测量值不限于 user-space-only(不包括在内核模式下花费的滴答声);这是另一种可能的影响。
如果您没有使用 -a
,如果您只计算 user-space 个周期,而不是花费在核心。 (例如 perf stat --all-user
,或者你的 kernel.perf_event_paranoid
设置足够高,不允许你在内核中分析硬件事件,这有效地将 :u
应用于硬件事件,但不会将它们打印为 cycles:u
.)
如果您将 kernel.perf_event_paranoid
sysctl 设置更改为 0,或 运行 perf
作为 root,您应该看到 800 MHz 作为周期 / task-clock,因为那是CPU 的速度是 运行ning 而你的线程是 运行ning.
不在 user-space 中花费大量周期表明您的代码在内核中花费了大量时间,如果您使用大数组,可能会处理页面错误。