大型“for”循环哪个更快:函数调用或内联编码?

Posted

技术标签:

【中文标题】大型“for”循环哪个更快:函数调用或内联编码?【英文标题】:Which is faster for large "for" loop: function call or inline coding? 【发布时间】:2010-05-04 19:54:28 【问题描述】:

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

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

我已经使要调用的函数变得更轻更短(但仍然可以正常工作),现在我开始认为撕掉该函数调用并直接在其中编写该过程会更快前两个 for 循环?

该系统中的处理器是 ARM7TDMI,频率为 55MHz。系统本身的时间要求不是很高,因此不必具备实时能力。然而,它处理职责的速度越快越好。

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

-zaplec

【问题讨论】:

写两个并比较它们。没有其他方法可以确定。当您无法访问分析工具(我猜您在嵌入式系统中没有)时,您必须测试这些东西。 你没有这么说,但是你有没有在上面运行分析器?在关注 for 循环或 while 循环哪个更快之前,您应该加倍确定您的算法没有做出愚蠢的假设。再说一遍,您对此运行分析器? 是的,绝对让它内联。还要告诉我们你在这个“关键函数”中做了什么......虽然循环并不比 for 循环快,但是如果你在代码中(重新)使用循环计数器很多,那么你可能会发现边际加速从 N 迭代到 0,而不是反过来。 同意剖析和使用剖析结果。我们无法知道哪种方法最适合您的具体情况。 @Welbog:您可以在使用周期精确指令集模拟器时部署分析工具。 ARM 的 GNU 工具链包括一个,Keil RealView 工具链和其他工具链也是如此 - 所以是的,您可以对其进行分析。 【参考方案1】:

试试看!!

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

...但它是否对现实世界有任何影响,只有您在尝试并确定结果后才能回答。

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

【讨论】:

我想这是唯一明智的做法,因为我预先优化了代码,因此可以很容易地进行这些更改。与简单的尝试和查看解决方案相比,将代码转换为汇编并估计性能可能会花费太多的工作。感谢大家的许多快速回答:)【参考方案2】:

您需要谨慎进行优化,因为您并不总是清楚编译器正在为您进行哪些优化。预优化是人们常犯的错误。您的代码可读性和易于维护还是稍微快一点很重要?就像其他人建议的那样,最好的方法是对不同的方法进行基准测试,看看是否有明显的差异。

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

【讨论】:

【参考方案3】:

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

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

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

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

另一种技术是针对Data Oriented Design 进行优化。还要检查this reference。

请记住为优化设置一个限制。这是您决定任何更多优化都不会产生任何投资回报或客户满意度的地方。此外,分阶段应用优化;当您的经理提出要求时,这将使您能够获得可交付成果。

【讨论】:

【参考方案4】:

对您的代码运行分析器。如果你只是在猜测你把时间花在了哪里,那你可能错了。分析器将显示哪个功能花费的时间最多,您可以专注于此。您可能在函数中执行的操作比函数调用本身花费的时间更长。您是否查看是否可以将浮点运算更改为整数,或将整数数学更改为移位?你可以花很多时间摆弄那些没有太大区别的东西。对您的代码运行分析器,并确定您正在更改的内容会有所作为。

【讨论】:

我对分析器不是很熟悉,但至少我会尝试一个。我想了解它们非常有价值:)【参考方案5】:

对于函数与内联,不幸的是没有简单的答案。 IE。这取决于。见this FAQ。对于“for”与“while”,我认为性能上没有任何显着差异。

【讨论】:

【参考方案6】:

一般来说,函数调用应该比内联有更多的开销。但是,您确实应该进行分析,因为这可能会受到编译器的很大影响(尤其是编译/优化设置)。例如,一些编译器会自动内联代码。

【讨论】:

以上是关于大型“for”循环哪个更快:函数调用或内联编码?的主要内容,如果未能解决你的问题,请参考以下文章

什么是内联函数

inline函数不能在for循环中使用的原因

内联函数和宏定义

SQL,While循环,递归存储过程或游标中哪个更快?

charAt() 还是子字符串?哪个更快?

更快的 For 循环在 Pandas 中处理数据