我正在研究一个(非常大的)现有的单线程C应用程序。在这种情况下,我修改了应用程序以执行一些非常少的额外工作,包括每次调用特殊函数时递增计数器(此函数被称为~80.000次)。该应用程序在运行64位Linux内核3.2.0-31-generic和-O3选项的Ubuntu 12.04上编译。
令人惊讶的是,代码的检测版本运行得更快,我正在调查原因。我使用clock_gettime(CLOCK_PROCESS_CPUTIME_ID)
测量执行时间并获得代表性结果,我报告的平均执行时间值超过100次运行。此外,为了避免来自外界的干扰,我尽可能地尝试在没有任何其他应用程序运行的系统中启动应用程序(在旁注中,因为CLOCK_PROCESS_CPUTIME_ID返回处理时间而不是挂钟时间,其他应用程序"应该"理论上只影响缓存而不是直接影响流程执行时间)
我怀疑"指令缓存效果",也许在缓存中更大(更少字节)适合不同且更好的检测代码是否可以想象?我尝试使用valegrind --tool = cachegrind进行一些缓存调查,但遗憾的是,已检测的版本(初看起来似乎合乎逻辑)比初始版本更多的缓存未命中。
有关此主题的任何提示以及可能有助于找到为什么检测代码运行得更快的想法都是受欢迎的(在一种情况下可以使用一些GCC优化而在另一种情况下没有,为什么?,...)
答案 0 :(得分:4)
由于问题中的细节不多,我只能在调查问题时建议考虑一些因素。
很少有额外的工作(例如递增计数器)可能会改变编译器是否应用某些优化的决定。编译器并不总是有足够的信息来做出完美的选择。它可能会尝试针对瓶颈是代码大小的速度进行优化。当没有太多要处理的数据时,它可能会尝试自动矢量化计算。编译器可能不知道要处理什么类型的数据或者将执行代码的CPU的确切模型是什么。
即使此更改不会影响编译器优化,也可能会改变CPU执行代码的方式。
要研究编译器优化的效果,可以在添加反递增代码之前和之后比较生成的汇编代码。
要调查CPU效果,请使用允许检查处理器性能计数器的分析器。
答案 1 :(得分:1)
根据我对嵌入式编译器的经验,编译器中的优化工具会寻找递归任务。也许额外的代码迫使编译器看到更加递归的东西,并且它以不同的方式构造机器代码。编译器为优化做了一些奇怪的事情。在某些语言中(我认为Perl?)“非not”条件的执行速度比“true”条件更快。您的调试工具是否允许您单步执行代码/程序集比较?这可以增加一些关于编译器决定如何处理额外任务的见解。