对于大型“for”循环来说哪个更快:函数调用还是内联编码?

时间:2010-05-04 19:54:29

标签: c embedded runtime inline-code function-call

我编写了一个嵌入式软件(当然使用C语言),现在我正在考虑改善系统运行时间的方法。我系统中最重要的单个模块是一个非常大的嵌套for循环模块。

该模块由两个嵌套的for循环组成,循环最多122500次。这还不是很多,但问题是嵌套for循环内部我有一个函数调用另一个源文件中的函数。该特定函数主要由两个嵌套for循环组成,循环总循环次数为22500次。所以现在我必须进行122500次函数调用。

我已经使这个函数被称为更轻更短(但仍然可以正常工作)现在我开始认为,扯掉那个函数调用并直接在那些函数中编写该进程会更快前两个for循环?

该系统中的处理器是ARM​​7TDMI,其频率为55MHz。系统本身并不是非常重要的时间,因此它不必具备实时能力。然而,处理其职责的速度越快越好。

使用while循环而不是fors也会更快吗?关于如何改善运行时间的任何建议都值得赞赏。

-zaplec

6 个答案:

答案 0 :(得分:19)

尝试并查看!!

几乎可以肯定会有所作为。函数调用开销通常不是那么大的问题,但是重复超过100K时它开始累加起来。

......但是,它是否会产生任何现实世界的差异,只有你可以在尝试并对结果进行计时后才能回答。

对于for vs while ...除非您在更改循环时实际更改行为,否则无关紧要。如果有疑问,请让编译器为两者编译汇编代码并进行比较......或者只是更改它并将其计时

答案 1 :(得分:3)

您需要注意所做的优化,因为您并不总是清楚编译器为您做了哪些优化。预优化是人们常犯的错误。您的代码是否可读且易于维护或稍快一点,这一点很重要吗?像其他人所建议的那样,最好的方法是对不同的方法进行基准测试,看看是否存在明显的差异。

如果你不相信你的编译器在优化方面做了很多工作,我会在优化C时看一些较旧的概念(在SO或google上搜索应提供一些好的链接)。

答案 2 :(得分:2)

ARM处理器有一个指令管道(缓存)。当处理器遇到分支(调用)指令时,它必须清除管道并重新加载,从而浪费一些时间。优化速度的一个目标是减少重新加载到指令流水线的次数。这意味着减少分支指令。

正如其他人在SO中所述,使用针对速度和配置文件的优化设置编译代码。我更喜欢查看汇编语言列表(从编译器打印或在调试器中交织显示)。使用此作为基线。如果无法分析,则可以使用汇编指令计数作为粗略估计。

下一步是减少分支数量;或分支的次数。展开循环有助于减少分支的使用次数。内联有助于减少分支数量。在应用这种微调技术之前,请查看设计和代码实现,以了解是否可以减少分支。例如,使用布尔算术或使用Karnaugh Maps减少“if”语句的数量。我最喜欢的是减少需求并消除不需要执行的代码。

在代码实现中,移动在forwhile循环之外不会更改的代码。一些循环可以简化为方程式(例如,用乘法替换加法循环)。此外,通过询问“这个循环真的需要多次执行”来减少迭代次数。

另一种技术是优化Data Oriented Design。另请查看this reference

请记住设置优化限制。您可以在此处决定更多优化不会产生任何投资回报率或客户满意度。此外,分阶段应用优化;这将允许您在经理要求时提供可交付成果。

答案 3 :(得分:1)

在您的代码上运行探查器。如果你只是猜测你花时间在哪里,你可能错了。分析器将显示哪些功能占用的时间最多,您可以专注于此。你可能在函数中做了一些比函数调用本身更长的事情。您是否想看看是否可以将浮动操作更改为整数,还是将整数数学更改为移位?你可以花很多时间摆弄那些没有太大作用的东西。在您的代码上运行一个分析器,并确保您正在更改的内容会有所作为。

答案 4 :(得分:0)

对于功能与内联,遗憾的是没有简单的答案。即这取决于。见this FAQ。对于“for”与“while”,我认为性能没有任何显着差异。

答案 5 :(得分:0)

通常,函数调用应该比内联具有更多的开销。你真的应该分析一下,因为你的编译器可能会对它产生很大的影响(特别是编译/优化设置)。例如,有些编译器会自动内联代码。