1

我想测量 C 程序中选定循环的运行时间,以便查看在这些循环中花费了执行程序(在 linux 上)的总时间的百分比。我应该能够指定应该测量性能的循环。在过去的几天里,我尝试了几种工具(vtune、hpctoolkit、oprofile),但似乎都没有。他们都发现了性能瓶颈,并只是展示了那些时间。那是因为这些工具只存储高于阈值(~1ms)的时间。因此,如果一个循环花费的时间少于此时间,则不会报告其执行时间。

gprof 的基本块计数功能取决于旧编译器中现在不支持的功能。

我可以手动编写一个简单的计时器使用gettimeofday或类似的东西,但在某些情况下它不会给出准确的结果。例如:

for (i = 0; i < 1000; ++i)
{
    for (j  = 0; j < N; ++j)
    {
        //do some work here
    }
}

现在在这里我想测量花费在内部循环中的总时间,我必须gettimeofday在第一个循环中调用。所以gettimeofday它自己会被调用 1000 次,这会引入自己的开销,结果会不准确。

4

3 回答 3

2

除非您的 CPU 周围有电路仿真器或分线盒,否则不存在对单循环或单指令进行计时这样的事情。您需要将测试运行扩大到每个至少需要几秒钟的时间,以减少由于 CPU、操作系统等中发生的其他事情而导致的错误。

如果您想准确了解特定循环执行所需的时间,并且执行时间不到 1 秒,您将需要人为地增加迭代次数以获得高于“本底噪声”的数字。然后,您可以将该数字除以人为夸大的迭代次数,得到一个数字,该数字表示通过目标循环需要多长时间。

如果您想比较不同循环样式或技术的性能,同样的事情也成立:您将需要增加迭代次数或通过您的测试代码,以获得测量结果重新感兴趣的主导你正在测量的时间片。

无论您是使用 CPU 提供的亚毫秒高性能计数器、系统日期时间时钟还是挂钟来测量测试经过的时间,这都是正确的。

否则,您只是在测量白噪声。

于 2010-04-29T19:06:08.670 回答
0

通常,如果您想测量在内部循环中花费的时间,您会将时间获取例程放在外部循环之外,然后除以(外部)循环计数。如果您希望任何内部循环的时间相对恒定j,那就是。

任何分析指令都会产生它们自己的开销,但大概不管插入到哪里,开销都是相同的,因此“一切都在洗礼”。大概您正在寻找两个比较进程的运行时之间存在相当大差异的地方,这样的一对函数调用不会成为问题(因为您也需要一个在“结束”处,以获得时间delta),因为一个例程的成本将是另一个例程的 2 倍或更多。

大多数平台也提供某种更高分辨率的计时器,尽管我们在这里使用的计时器隐藏在 API 后面,因此“客户端”代码是跨平台的。我敢肯定,只要稍微看一下,您就可以打开它。尽管即使在这里,您获得优于 1 毫秒精度的可能性也很小,因此最好连续运行代码多次并为整个运行计时(然后除以循环计数,natch)。

于 2010-04-29T18:51:44.337 回答
0

我很高兴您正在寻找百分比,因为这很容易获得。让它运行。如果它运行得很快,请在它周围放置一个外循环,这样它会花费很长时间。这不会影响百分比。在它运行时,获取stackshots您可以使用gdb中的 Ctrl-Break 执行此操作,也可以使用pstacklsstack。只需看看有多少百分比的堆栈快照显示您关心的代码。

假设循环需要一小部分时间,例如 0.2 (20%),并且您需要 N=20 个样本。那么应该显示它们的样本数将平均为 20 * 0.2 = 4,并且样本数的标准偏差将为 sqrt(20 * 0.2 * 0.8) = sqrt(3.2) = 1.8,所以如果你想要更高的精度,采集更多样本。(我个人认为精度被高估了。)

于 2010-04-30T14:44:01.517 回答