1

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

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

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

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

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

-zaplec

4

6 回答 6

19

试试看!

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

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

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

于 2010-05-04T19:57:01.853 回答
3

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

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

于 2010-05-04T20:02:11.217 回答
2

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

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

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

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

另一种技术是优化面向数据的设计。还要检查这个参考

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

于 2010-05-04T22:36:49.650 回答
1

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

于 2010-05-04T20:10:28.857 回答
0

对于函数与内联,不幸的是没有简单的答案。即这取决于。请参阅此常见问题解答。对于“for”与“while”,我认为性能没有任何显着差异。

于 2010-05-04T20:01:42.803 回答
0

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

于 2010-05-04T22:41:09.747 回答