我在Linux上使用C,并希望为不同的输入大小计算代码的性能。代码用于解决PDE的数值方法,我来自一个坚实的基础来预测代码的执行时间。
我遇到的问题是记录特定问题的时间结果。对于我遇到的所有问题,除了一个,使用clock()来获得开始和结束时间给出了我期望它们的时间。也就是说,如果大小为N的输入花费时间T,那么大小为4N的输入将花费时间4T。对于一个问题,情况并非如此(启用和不启用优化标志)。为了试图弄清楚发生了什么,我使用分析器(gprof)运行代码,在这种情况下,分析器告诉我代码需要一些时间来执行,这离时钟()时间很远给出。下面显示的结果是gprof中给出的时间,并且在没有-gp重新编译相同代码时给出使用clock()的时间。作为完整性检查,编译所有代码时不设置任何优化标志
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和控制台的输出很少,所以在程序可能会挂起大量时间的情况下应该没有任何内容
答案 0 :(得分:2)
gprof所做的是每秒对程序计数器进行100次采样,并且每次查看它是否能够确定程序计数器所处的功能。 (它还跟踪任何函数调用任何其他函数的次数。) 但仅为使用-pg编译的函数执行此操作。
假设程序计数器在数学库中,因为这就是你所调用的,但是数学库没有用-pg编译。 gprof基本上会扔掉样品。
看,gprof是一个值得尊敬的工具,但是stackoverflow充满了试图理解它的问题。 除了没有调用任何库函数的程序,不进行递归,并且不进行任何I / O(即玩具程序)之外,不要指望任何类似精确测量的东西。
获得执行时间测量的最佳方法就是你正在做的事情 - 简单的整体时间。 如果你想要更多的精度数字,只需重复执行N次并除以N.
另一方面,如果您希望查看函数或代码行花费的时间分数,则仅限程序计数器(独占或自身时间)并包括被调用者(包括你需要得到堆栈样本。 (因为包含分数=堆栈上的时间分数,而独占分数=堆栈 end 的时间分数。) 一些分析师这样做。许多人只是do it manually,如果他们满足于低精度。 如果执行可能包括对阻塞函数(如睡眠,互斥等待或I / O)的调用,并且您不希望将其排除,则需要在挂钟时间内采样。 Very few profilers这样做,但显然是手动方法。