如何在没有函数调用的情况下在 Linux 中检索处理器时间?

Phi*_*ias -2 c c++ unix linux assembly

我需要计算一部分(C++)代码的运行时间,并希望通过查找代码执行过程中经过的时钟滴答数来实现这一点。

我想找到代码开头的处理器时间和结尾处的处理器时间,然后减去它们以找到经过的滴答数。

这可以通过时钟功能来完成。然而,我测量的时间需要非常精确,并且使用函数调用被证明是非常具有侵入性的,因为调用者保存的寄存器分配器在每次调用时都会溢出许多变量。

因此,我不能使用任何函数调用,需要自己检索处理器时间。汇编代码没问题。

我正在使用 Debian 和 i7 Intel 处理器。我不能使用分析器,因为它太具有侵入性。

Bas*_*tch 5

你应该阅读time(7)。请注意,即使是用汇编程序编写的,您的程序也会在任意时刻重新安排(可能每毫秒进行一次上下文切换;另/proc/interrupts请查看并查看proc(5))。那么任何硬件定时器都是没有意义的。即使使用RDTSCX86-64机器指令读取硬件时间戳计数器是无用的(因为之后的任何上下文切换将错就错,和Linux内核是做抢占的调度,并随时都有可能发生)。

您应该考虑clock_gettime(2)。由于vdso(7) ,它真的很快(在我的 i5-4690S 上大约 3.5 或 4 纳秒,在测量对它的数千次调用时。顺便说一句,这是一个系统调用,因此您可以直接编写汇编器指令来执行它们。我认为不值得麻烦(并且可能比 vdso 调用)。

顺便说一句,任何类型的分析或基准测试在某种程度上都是侵入性的。

最后,如果您的基准函数运行得非常快(远小于一微秒),缓存未命中变得很重要,甚至占主导地位(请记住,需要有效访问 DRAM 模块的 L3 缓存未命中持续数百纳秒,足以运行数百条机器指令在 L1 I 缓存中)。您可能(并且可能应该)尝试对多个(数百个)连续调用进行基准测试。但是您将无法准确地进行测量。

因此,我相信不能做得比使用更好clock_gettime我不明白为什么它对你的情况来说不够好......顺便说一句,时钟(3)正在调用clock_gettimeCLOCK_PROCESS_CPUTIME_ID所以恕我直言它应该足够了,而且更简单。

换句话说,我认为避免任何函数调用是您的误解。请记住,函数调用开销比缓存未命中要便宜得多!

请参阅相关问题的答案(与您的问题一样不清楚);还可以考虑使用 perf(1)gprof(1)oprofile(1)time(1)。看到这个

最后,您应该考虑要求编译器进行更多优化。你有没有考虑编译和链接g++ -O3 -flto -march=native(带链接时优化)。

如果您的代码具有数值和向量性质(如此明显且可大规模并行化),您甚至可以考虑花费数月的开发时间将其核心代码(数值计算内核)移植到OpenCLCUDA 中的GPGPU上。但是你确定这样的努力值得吗?更换硬件时,您需要调整和重新开发代码!

您还可以重新设计您的应用程序以使用多线程JIT 编译部分评估元编程技术、多处理云计算(使用进程间通信,例如socket(7) -s,可能使用0mq或其他消息传递库) . 这可能需要多年的发展。有没有银弹

(不要忘记考虑开发成本;如果可能,更喜欢算法改进。)

  • @FarhadYusufali:那是因为避免函数调用是不切实际的,而且可能是不必要的。我们中的大多数人都尝试过做类似的事情,但发现使用粗制计时器(如秒表)同时更改程序以在审查下重复代码多次(如一百万次)“足够好”。几乎所有现代 CPU 都有多种时序可变性:内存缓存、寄存器前瞻、分支预测等。 (4认同)
  • @FarhadYusufali 您正在尝试使用千分尺来测量用斧头切割的东西。结果不会像您认为的那样精确。 (4认同)