有没有比计时更好的方法来对 C 程序进行基准测试?

Posted

技术标签:

【中文标题】有没有比计时更好的方法来对 C 程序进行基准测试?【英文标题】:Is there a better way to benchmark a C program than timing? 【发布时间】:2011-11-19 08:19:12 【问题描述】:

我正在编写一个小程序,它必须对一个大数组(最多 400 万个文本字符串)进行排序。似乎我在这方面做得很好,因为 radixsort 和 mergesort 的组合已经将原始 q(uick)sort 执行时间缩短了不到一半。

执行时间是重点,因为这是我用来基准测试我的一段代码的时间。

我的问题是:

有没有比只计算执行时间更好(即更可靠)的方法来对程序进行基准测试?它有点工作,但是如果运行两次,相同的程序(运行相同的后台进程)通常执行时间略有不同。

这有点违背了检测小改进的目的。几个小的改进可以加起来一个大的......

提前感谢您的任何意见!

结果:

我设法让 gprof 在 Windows 下工作(使用 gcc 和 MinGW)。与我的普通编译器 (tcc) 相比,gcc 的行为很差(考虑到执行时间),但它给了我一些见解。

【问题讨论】:

@delnan:是的,因为用于详细分析的工具是特定于语言的。 Prolog 的 time/1 和 IPython 的 timeit 在 C 程序中不起作用:) 如何正确计时:***.com/questions/2349776/… ***.com/questions/375913/… 【参考方案1】:

尝试使用分析工具,它还会向您显示程序在哪里花费时间。 gprof 是经典的 C 分析工具,至少在 Unix 上是这样。

【讨论】:

这个想法+1。我会推荐 Valgrind 的 Callgrind 而不是 gprof。如果你在 KDE 上,Valgrind 和 Callgrind 都有一个不错的 gui 前端,但我不记得名字了。 @San:你的意思可能是kcachegrind,是的,它是一个很棒的工具。【参考方案2】:

查看time 命令。它跟踪进程使用的 CPU 时间和挂钟时间。您还可以使用 gprof 之类的东西来分析您的代码,以找到您的程序中实际花费最多时间的部分。您可以在代码中使用计时器进行低技术版本的分析。 Boost 有一个很好的 timer 类,但很容易自己动手。

【讨论】:

Windows 是否有相当于 Linux 的时间? 显然在windows中有类似的东西。第一个回答这个question【参考方案3】:

我认为仅衡量一段代码执行所需的时间是不够的。您的环境是一个不断变化的事物,因此您必须采用统计方法来衡量执行时间。

基本上您需要进行N 测量,丢弃异常值,并使用不确定性测量计算您的平均、中值和标准差运行时间。

这是一个很好的博客,解释了为什么以及如何做到这一点(带有代码):http://blogs.perl.org/users/steffen_mueller/2010/09/your-benchmarks-suck.html

【讨论】:

【参考方案4】:

到目前为止,您使用什么来计时执行时间?对于初学者,time.h 中有 C89 clock()。在 unixoid 系统上,您可能会发现 getitimer() 用于 ITIMER_VIRTUAL 来测量进程 CPU 时间。有关详细信息,请参阅相应的手册页。

您还可以使用 POSIX shell 的 times 实用程序对进程及其子进程使用的处理器时间进行基准测试。分辨率取决于系统,就像关于分析的任何事情一样。尝试将您的 C 代码包装在一个循环中,尽可能多地执行它,以减少基准测试报告时的“抖动”。

【讨论】:

我正在使用时钟()。奇怪的是,它有时会给我几毫秒,有时它会四舍五入到 10 秒...... 你是否除以CLOCKS_PER_SEC 得到以秒为单位的值?【参考方案5】:

从测试工具中调用您的例程,从而执行 N + 1 次。忽略第一次迭代的时间,然后取迭代 1..N 的平均值。第一次忽略的原因是由于各种影响,它通常会略微膨胀,例如虚拟内存、被分页的代码等。平均 N 次迭代的原因是您摆脱了由其他进程、调度程序等引起的伪影。

如果您在 Linux 或类似系统上运行您可能还想使用 taskset 将您的代码固定到特定的 CPU 内核(假设它是单线程的),理想情况下不是内核 0,因为这往往会处理所有中断.

【讨论】:

我会尝试迭代。是否有相当于 Windows 的任务集? @Dennis:抱歉 - 我不使用 Windows - 我相信在最新版本的 Windows 中有某种 CPU 关联 API,但可能没有命令行工具,除非 cygwin 或类似工具有。

以上是关于有没有比计时更好的方法来对 C 程序进行基准测试?的主要内容,如果未能解决你的问题,请参考以下文章

为啥返回 Java 对象引用比返回原语慢得多

使用 Java 进行硬盘基准测试,得到不合理的快速结果

刷新缓存以防止基准测试波动

用于 hget 和 hset 命令的 Redis 基准测试

如何在持续集成中包含谷歌基准

从Int获取单个数字而不使用字符串?