【发布时间】:2016-10-21 03:11:14
【问题描述】:
好吧,这将是一个没有细节的问题,因为我不知道如何更好地解释。对不起。我有一个内存密集型 C 程序(很多指针)。我有一个源代码,它是我用 gcc -O2 编译的。我在 Ubuntu Linux 上。在程序开始和结束时,会调用 clock() 来测量经过的时间。此外,我正在使用 time 命令来检查时间。问题是同一个程序有时在不改变任何东西的情况下会快 20% 以上(或慢)。
$ date; time ./cudd-example-8queens
pon jun 20 00:49:05 CEST 2016
CPU TIME = 6.46
real 0m6.475s
user 0m6.405s
sys 0m0.067s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:16 CEST 2016
CPU TIME = 8.03
real 0m8.051s
user 0m7.995s
sys 0m0.048s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:33 CEST 2016
CPU TIME = 6.48
real 0m6.490s
user 0m6.445s
sys 0m0.040s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:42 CEST 2016
CPU TIME = 6.45
real 0m6.469s
user 0m6.424s
sys 0m0.040s
$ date; time ./cudd-example-8queens
pon jun 20 00:49:56 CEST 2016
CPU TIME = 8.04
real 0m8.058s
user 0m7.982s
sys 0m0.068s
我的问题是:如何解释这种差异,即这额外的 1.5 秒(有时甚至更糟)花在了哪里?它必须是具有内存访问权限的东西,但是如何检查呢?
编辑:我已经安装了 perf,这里有两个结果(我已经更新它们以显示从 cpupower 获得的信息)。关于目标,我正在比较科学算法,这对我来说很重要,例如一个比另一个快 10%。
$ date; cpupower -c all frequency-info -f; perf stat -B ./cudd-example-8queens
pon jun 20 12:39:21 CEST 2016
analyzing CPU 0:
1300000
analyzing CPU 1:
1300000
analyzing CPU 2:
1300000
analyzing CPU 3:
1300000
clock() TIME = 6.70
clock_gettime() TIME = 6.70
Performance counter stats for './cudd-example-8queens':
6705,796274 task-clock (msec) # 0,999 CPUs utilized
104 context-switches # 0,016 K/sec
3 cpu-migrations # 0,000 K/sec
30861 page-faults # 0,005 M/sec
17295862806 cycles # 2,579 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
7361712951 instructions # 0,43 insns per cycle
1228059232 branches # 183,134 M/sec
64491733 branch-misses # 5,25% of all branches
6,709414218 seconds time elapsed
$ date; cpupower -c all frequency-info -f; perf stat -B ./cudd-example-8queens
pon jun 20 12:39:30 CEST 2016
analyzing CPU 0:
1300000
analyzing CPU 1:
1300000
analyzing CPU 2:
1300000
analyzing CPU 3:
1300000
clock() TIME = 8.43
clock_gettime() TIME = 8.43
Performance counter stats for './cudd-example-8queens':
8441,824238 task-clock (msec) # 0,999 CPUs utilized
145 context-switches # 0,017 K/sec
3 cpu-migrations # 0,000 K/sec
30863 page-faults # 0,004 M/sec
13958245339 cycles # 1,653 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
7360082448 instructions # 0,53 insns per cycle
1227803521 branches # 145,443 M/sec
64517871 branch-misses # 5,25% of all branches
8,446645648 seconds time elapsed
EDIT2:我的英特尔 NUC 有英特尔酷睿 i5-4250U CPU。因此,使用“cpupower frequency-set”的建议很有希望,但不幸的是它没有任何帮助。此外,我使用“clock()”和“clock_gettime(CLOCK_PROCESS_CPUTIME_ID)”得到完全相同的结果,这些结果也被 perf 的“task-clock (msec)”确认。
【问题讨论】:
-
使用像
perf这样的体面分析工具,否则您将无法了解全部内容。 -
@l'L'l 所说的……另外,您处于多用户、多任务环境中。为单个任务计时可能几乎没有意义。 ..然后有例如/dev/urandom 如果你要使用它的状态...
-
在测量程序的速度时,
elapsed time几乎没有用,因为它包括了其他进程运行的时间。更好的方法是调用:clock_gettime(),参数为:CLOCK_PROCESS_CPUTIME_ID,它获取当前进程的进程时间。注意:始终检查返回值-1,因为这表明调用失败。注意:程序的第一行应该是:#define _POSIX_C_SOURCE (199309L) -
还要确保通过
sudo cpupower frequency-set -g performance禁用CPU频率缩放 -
谢谢,但不幸的是 clock_gettime() 和 cpupower 没有帮助(见 EDIT2)。
标签: c linux performance memory-management profiling