我希望知道在Linux下,程序执行所需的时间,单位为微秒(或更高的精度)。目前我使用的是time
命令,但它只能提供最大毫秒级别的准确度。是否有一些方法可以调整time
命令以获得更高的准确度,或者有其他命令可以实现相同的功能?
我同意Employed Russian's answer。对于这样的测量,希望微秒级别的准确度并没有太多意义。因此,你所获得的任何附加数字都是无意义的(实际上是随机的)。
如果你有要测量的应用程序的源代码,可以使用clock或clock_gettime函数,但不要指望超过几十微秒的准确度。还有RDTSC机器指令。
不要忘记,从应用程序的角度来看,执行时间是不确定和不可重现的(考虑到上下文切换、缓存未命中、中断等在随机时间发生)。
如果你想要衡量整个程序的性能,请至少运行几秒钟,并测量时间多次(例如8次),然后取平均值(也许去掉最好和最差的计时)。gprof
,oprofile
等等...)。还可以参考这个问题。main
中添加一些循环或使用更大的数据集...),并重复执行基准命令十几次。然后取这些度量值的平均值(或最差值、最好值,具体取决于您想要的内容)。顺便提一下,我的i3770K最近在GNU/Linux(4.2内核,Debian/Sid/x86-64)桌面电脑上,“系统”调用比如time(2)或clock_gettime(2)执行时间约为3到4纳秒(多亏了vdso(7)避免了真正的syscall负担...),所以你可以经常在程序内部使用它们。
time_t t0 = time(NULL); clock_t c0 = clock(); while (1) { printf("\r%ld", (clock() - c0) / CLOCKS_PER_SEC - (time(NULL) - t0)); }
- ssmidLinux perf
CLI 工具
像其他人提到的那样,微秒级别的时间在现代系统中只是噪音。
在 Linux 中实现微秒级(或更高)进程计时 询问是否有任何方法可以减少内核产生的变异性。
perf
CLI 工具可以打印微秒及更多信息,这将使我们能够看到这些测量值只是噪音的程度。
Ubuntu 22.04 设置:
sudo apt install linux-tools-common linux-tools-generic
echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
循环CYCLES
个周期的x86汇编程序:
main.S
.text
.global _start
_start:
mov $0, %rax
mov $CYCLES, %rcx
.Lloop_label:
inc %rax
loop .Lloop_label
/* exit */
mov $60, %rax /* syscall number */
mov $0, %rdi /* exit status */
syscall
组装并运行:
cpp -DCYCLES=100000 main.S main.cpp.S
as -o main.o main.cpp.S
ld -o main.out main.o
perf stat ./main.out
在我的Lenovo ThinkPad P51上进行的一些样本结果:
CYCLES |
经过的时间(秒) |
---|---|
10^9 | 1.3秒 |
10^8 | 0.13秒 |
10^7 | 0.014秒 |
10^6 | 1.9毫秒 |
10^5 | 0.6 - 0.8毫秒 |
10^4 | 0.4 - 0.8毫秒 |
从这里我们可以看到,毫秒级别的数字在某种程度上是有意义的,并且随着规模的增大而有所缩放:循环次数减少10倍意味着时间减少10倍。
但是,在大约0.1毫秒左右,事情完全停止了缩放,我们必须测量完全随机的其他东西,而不是程序执行。
你也可以尝试创建裸机程序:如何在没有操作系统的情况下运行程序? 我想知道在这种情况下BIOS和硬件本身会产生多少噪音,这将是一个有趣的尝试。
time /bin/sleep 0.006
进行快速测试,似乎表明噪声小于1毫秒。因此,尽管此类测量肯定存在风险,但Guanidene的请求本身并非毫无意义。 - Joachim Breitner