分析时间与 clock() 时间无关

Posted

技术标签:

【中文标题】分析时间与 clock() 时间无关【英文标题】:Profiled time does not relate to clock() time 【发布时间】:2014-09-02 14:39:20 【问题描述】:

我在 Linux 上使用 C,并且希望针对不同的输入大小对我的代码的性能进行计时。该代码用于求解偏微分方程的数值方法,我来自可靠的基础来预测代码的执行时间。

我遇到的问题是在记录特定问题的计时结果时。对于我遇到的所有问题,除了一个,使用 clock() 来获取开始和结束时间会给出我期望的时间。也就是说,如果大小为 N 的输入花费时间 T,那么大小为 4N 的输入将花费时间 4T。对于一个问题,情况并非如此(打开和不打开优化标志)。为了尝试弄清楚发生了什么,我使用分析器(gprof)运行代码,在这种情况下,分析器告诉我代码需要一些时间来执行,这与 clock() 时间相差甚远给出。下面显示的结果是gprof中给出的时间,使用clock()的时间是在没有-gp的情况下重新编译相同的代码时给出的。作为健全性检查,所有代码都在没有设置任何优化标志的情况下编译

   Input size   |   Time (clock())   |   Time (gprof)
     256x256    |       122.77       |       32.14
     512x512    |       538.94       |      128.37
    1024x1024   |      2712.67       |      511.22

我使用 gprof 获得的缩放是我想要的,但是当我执行代码而不进行任何分析时,代码本身的执行时间(挂钟时间)与打开分析时(即很奇怪)并且缩放不再是预期的 4 因子。对于为什么会这样,有什么解释吗?

我认为对于上述结果的问题唯一不同的是,我广泛使用了具有分数幂的 pow() 函数,根据一些研究,据说该函数运行非常缓慢。但是,我预计放缓是统一的,因此时间的缩放应该仍然是统一的。请注意,我没有使用文件 I/O,而且控制台的输出也很少,所以程序可能会长时间挂起的地方应该没有任何东西

【问题讨论】:

如果是多线程应用,可能是这样的:***.com/a/25625385/1756405 @MadScienceDreams 否。这是一个单线程串行代码。一切都以一种很好的可预测方式计算(至少我认为它是可预测的) 尝试使用另一个分析器并将结果粘贴到此处 您真正的问题是,clock() 使用的是“实际”RTC 时钟,它将显示从开始到结束所经过的时间,而分析器将仅显示在被分析的应用程序中花费的时间。 IE。操作系统占用剩余时间。 @user3629249 我认为在 Linux 上 clock() 计算当前应用程序的 CPU 滴答声,而不是自启动以来经过的 CPU 滴答声。此外,对于其他问题(代码 90% 相同),clock() 时间更接近分析器所说的时间,所以我很高兴操作系统只花费了一点额外的时间跨度> 【参考方案1】:

gprof 的作用是每秒对程序计数器进行 100 次采样,每次都看它是否能确定程序计数器在哪个函数中。 (它还跟踪任何函数调用任何其他函数的次数。) 但它对使用 -pg 编译的函数执行此操作。

假设程序计数器在数学库中,因为这是你调用的,但是数学库不是用 -pg 编译的。 gprof 基本上会扔掉样本。

看,gprof 是一个古老的工具,但 *** 充满了试图理解它的问题。 除了不调用任何库函数、不执行递归和不执行任何 I/O 的程序(即玩具程序)之外,不要期望得到任何精确测量之类的东西。

测量执行时间的最佳方法就是您正在做的事情 - 简单的整体计时。 如果您想要更多位的精度,只需重复执行 N 次并除以 N。

另一方面,如果您想查看函数或代码行花费了多少时间,包括仅程序计数器(独占时间或自身时间)和包括被调用者(包括时间)您需要获取堆栈样本。 (因为包含分数 = 堆栈上的时间分数,而独占分数 = 堆栈结束的时间分数。) 一些分析器会这样做。如果他们满足于低精度,很多人只是do it manually。 如果执行可能包括对阻塞函数(如睡眠、互斥等待或 I/O)的调用,并且您不希望将其排除在外,则需要在挂钟时间采集样本。 Very few profilers 这样做,但显然手动方法会这样做。

【讨论】:

感谢您的回答。我会补充一点。我发现这个问题是 c 中的“pow”函数,它已知很慢(see here)。因此,gprof 不计算花在“pow”上的时间是有道理的,但在这种情况下,这正是我感兴趣的。我只想知道我的代码有多好,而不是它运行得有多好其他人的(可能很慢)代码 @Keeran:手动采样显示 pow、exp 和 log 花费了很大一部分时间(解决药物计量学中的 ODE)。它还向我表明,论点通常与以前相同。所以我记住了它们(制作了一个记住以前结果的包装函数)。非常好的加速。 这可能是一个想法,但不幸的是我的值不一样,而且我对高精度感兴趣,所以我也无法对值进行直方图。由于之前的海报,我还发现了使用 valgrind 进行手动采样的乐趣——太棒了!我已经切换到 icc 编译器,这对于一些初步的小型运行来说要好得多,希望对更长的运行也有好处

以上是关于分析时间与 clock() 时间无关的主要内容,如果未能解决你的问题,请参考以下文章

SylixOS下移植glib时clock_gettime函数分析

C 中的性能/分析测量

第二章,循环结构,输入输出,clock

OpenCL clock_gettime vs 内核分析:奇怪的结果

Libevent源码分析--- 时间管理

Libevent源码分析--- 时间管理