我该如何在C语言中对性能优化进行单元测试?

6
我一直在开发一个可移植的C库,用于图像处理。我花费了相当多的时间来编写几个低级函数,以便利用GCC自动向量化模式(根据目标处理器使用SSE和/或AVX),同时仍保留了一些可移植的C代码(使用的扩展:restrict和__builtin_assume_aligned)。
现在是时候在Windows上测试代码了(使用MSVC编译器)。但在此之前,我想设置某种单元测试,以避免出现问题,并且不会因为疏忽而丢失所有精心选择的指令,以便保留GCC自动向量化代码。
我可以简单地使用#ifdef / #endif隐藏整个函数体,但我考虑更长远的解决方案,该方案将检测编译器更新时的任何退化。
我对单元测试相当有信心(有大量优秀的框架可用),但对此类低级功能的单元测试则不太自信。如何在诸如Jenkins之类的CI服务中集成性能单元测试?
注:我希望避免存储基于特定处理器的硬编码计时结果。
// start timer:
gettimeofday(&t1, NULL);
// call optimized function:
...
// stop timer:
gettimeofday(&t2, NULL);
// hard code some magic number:
if( t2.tv_sec - t1.tv_sec > 42 ) return EXIT_FAILURE;

1
你是否有未经优化的(通用)函数?最好与它们比较执行时间...这意味着t_opt预计会小于t_non_opt...但即使如此也不能百分之百保证。其他进程可能会同时进行随机磁盘访问,你的测试随时可能被抢占...还有一堆其他事情可能发生在你的测试之外... - zaufi
你的目标是什么?你想确保在修改后你的代码仍然正确(那么你将进行单元测试),还是想检查生成的代码的性能(这是不同的事情,可以用不同的方法来处理)?在后一种情况下,你甚至可能想打印出生成的汇编代码,以便与你的期望进行比较。 - Dirk Herrmann
@DirkHerrmann 这就是重点!我如何打印“可移植”的汇编代码?这可能取决于确切的gcc版本,如果您熟悉生成汇编代码,请提供更多详细信息。 - malat
@malat(可能有点偏离,但既然你习惯了GCC..)为什么一定要用MSVC?为什么不能使用mingw-w64呢?(因此再次使用GCC?更不用说,你可以编写C99甚至更好的C11,而不是非常古老(且有限)的C89,这是MSVC支持的唯一标准) - Peter Varo
1
你是否考虑过像Google Benchmark或类似的微基准测试框架? - Alexander Oh
2个回答

1
你的问题基本上可以归结为两个部分:
1. 怎样对你精心优化的代码进行性能基准测试? 2. 如何比较比较结果,以便检测代码更改和/或编译器更新是否影响了代码的性能? Google Benchmark 框架可能提供了解决问题 #1 的合理方法。它是 C++ 编写的,但这并不妨碍你从中调用你的 C 函数。
这个库可以生成各种格式的摘要报告,包括 JSON 和老式的 CSV。你可以安排将这些报告存储在每次运行时的某个地方。
然后,你可以编写一个简单的 Perl/Python 等脚本来比较基准测试的结果,并在它们偏离某个阈值以上时发出警报。
你必须注意的一件事是,在你的结果中可能存在由负载等变量引起的噪声。你没有详细说明你正在运行测试的环境,但如果它是(例如)一个包含其他虚拟机的主机上的虚拟机,则你的测试结果可能会受到其他虚拟机中发生的任何事情的影响。

诸如Jenkins之类的CI框架允许您编写脚本来执行测试时需要采取的操作,因此将此方法集成到这些框架中应该相对容易。


1

一种简单且可重复测量性能的方法是通过valgrind/callgrind运行基准测试单元。这将给出许多指标,例如:指令和数据读写事务(在不同的缓存深度下),总线阻塞交易等。您只需将这些值与已知的良好起始值进行比较即可。

由于Valgrind模拟了代码的运行,因此它具有可重复性。当然,它比直接运行代码要慢得多,但这使其独立于系统负载等因素。

如果在Windows中无法使用Valgrind(虽然有关Linux上的valgrind+wine+Windows程序的提及),则dynamoRIO是一个选择。它提供了类似于Valgrind的工具,如指令计数器和内存和缓存使用分析器。(此文撰写时,在Linux上可用,而在OS X上似乎半移植)


1
不可在Windows上移植,但至少提供比仅测试时间更多的详细信息。 - malat
有提到valgrind+wine的设置,但是可能会变得复杂。 - hmijail
@malat,如果你还在处理这个问题,我刚刚发现了一个可能相当于Windows版本valgrind各种工具的东西:http://dynamorio.org/(请查看“指令计数工具inscount”和“多进程在线缓存模拟器drcachesim”)。 - hmijail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接