我需要为Raspberry Pi编写一个高度优化的程序。 75%的OCed CPU(总共900 Mhz)已经使用,我的代码可能不是最后一块。
程序需要在循环中多次访问数组中的相同数据。我知道提取值并放在临时变量中更具可读性。但它是否加快了处理/缩短查找的CPU时间?
我正在编译并直接在Raspberry Pi(模型B)上构建,如果它改变了什么。该项目使用基于内核3.2.27的自定义Linux分支。 Gcc / g ++信息(结果相同):
$ gcc -v
[...]
Thread model: posix
gcc version 4.6.3 (Debian 4.6.3-14+rpi1)
答案 0 :(得分:2)
首先,一个巨大的警告。
还没有瓶颈,它仍然是WIP,但我想在过程的早期避免瓶颈,所以我不必在部署阶段/部署代码后将它们排除在外。无论如何,优化代码或扩展知识并没有什么坏处。
优化代码肯定会造成伤害。你在做什么是“过早优化”。性能肯定是代码度量,有时是最重要的。但是,针对性能优化的代码往往会减少构成“良好代码”的几乎所有其他指标:可理解性,可移植性,可维护性,可测试性等。在您知道需要这样做之前不要进行优化。
您还在询问这里的小优化。更大的一个:假设你的算法是O(N 2 ),并且在文献中有一个O(N * log(N))算法做了完全相同的事情。您可以将O(N 2 )优化为完全不可读,不可维护,不可测试的状态,但只能看到性能的微小提升。或者您可以切换到O(N * log(N))算法并拥有干净,可维护的代码。
那就是说,是的,把东西放在局部变量中可能会有所帮助,但它也会受到伤害。有时,编译器会将这些多个数组访问优化为编译器发明的临时变量。如果是这种情况,那些局部变量只是噪声,可能会使编译器混淆并使生成的代码变慢。
有时编译器不会优化那些多数组访问。当它不能优化那些访问时,将内容存储到局部变量有帮助。不要再猜测编译器。看看它在做什么。
使用局部变量还有另一种途径。阻止编译器优化那些对同一数组元素的多次访问的事情之一是使用多个指针。编译器不知道foo[index1]
是否指向内存中与bar[index2]
相同的位置。假设您在访问bar[index2]
之间写入foo[index1]
。编译器无法优化对foo[index1]
的第二次访问,因为该值可能已更改。
最好的方法是以某种方式向编译器承诺,foo
指向的内存没有别名。 C标准提供restrict
关键字来做到这一点。如果这是C,则可以使用foo
限定restrict
,从而使编译器能够将对foo[index1]
的多次访问优化为一个。
一个小问题:restrict
关键字不在C ++中(尚未)。但是,gcc(以及clang)提供__restrict__
关键字来执行相同的操作。
答案 1 :(得分:0)
最有可能的是,这将被优化掉。但请记住,由于处理器缓存,访问紧凑存储在内存中的数据会更便宜。