c++ - 如何在不调用函数的情况下在 Linux 中检索处理器时间?

标签 c++ c linux unix assembly

我需要计算一部分 (C++) 代码的运行时间,并希望通过查找代码执行期间经过的时钟周期数来实现此目的。

我想找到代码开头处的处理器时间和末尾处的处理器时间,然后将它们相减以找到经过的时钟周期数。

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

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

我使用的是 Debian 和 i7 Intel 处理器。我无法使用探查器,因为它的侵入性太强。

最佳答案

您应该阅读time(7) 。请注意,即使用汇编程序编写,您的程序也会在任意时刻重新安排(可能每毫秒 context switch ;另请参阅 /proc/interrupts 并查看 proc(5) )。那么任何硬件定时器都是没有意义的。偶using RDTSC x86-64 机器指令来读取 hardware timestamp counter是无用的(因为在任何上下文切换之后都会出错,并且 Linux 内核正在执行 preemptive 调度,这确实随时发生)。

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

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

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

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

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

参见this answer一个相关的问题(和你的问题一样不清楚);还可以考虑使用 perf(1) , gprof(1) , oprofile(1) , time(1) 。请参阅this .

最后,你应该考虑询问更多optimizations来自你的编译器。您是否考虑过使用 g++ -O3 -flto -march=native 进行编译和链接(带有链接时优化)。

如果您的代码具有数值和 vector 性质(非常明显且可大规模并行),您甚至可以考虑花费的开发时间将其核心代码(数值 compute kernels )移植到你的GPGPUOpenCLCUDA 。但你确定这样的努力值得吗?更改硬件时,您需要调整和重新开发代码!

您还可以重新设计您的应用程序以使用 multi-threading , JIT compilationpartial evaluationmetaprogramming技术,multiprocessingcloud-computing (使用 inter-process communication ,例如 socket(7) -s,可能使用 0mq 或其他消息传递库)。这可能需要数年的开发。有No Silver Bullet .

(不要忘记考虑开发成本;尽可能首选算法改进。)

关于c++ - 如何在不调用函数的情况下在 Linux 中检索处理器时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47003535/

相关文章:

C++ Cmake boost lib不断抛出很多错误

c++ - 如何像 std::function 一样改变模板实例化的外观

c++ - utf8 识别 strncpy

c++ - 绑定(bind) : Socket operation on non-socket

c++ - 多线程环境下MySQL C++ Connector的使用

Calc atan2 与 NEON

c - 有没有办法在不使用共享内存的情况下更改另一个进程的数据?

c - 如何从给定索引strcat和strcpy一个字符串?

linux - 复制过去 24 小时内容更改的特定命名目录

linux - 在 Jupyter 笔记本的单元格内执行时,无法使用 "cd"命令更改目录