为什么使用指针(低优化)会使程序更快?
Why using pointers (with low optimization) makes the program faster?
我正在学习有关嵌入式 C 编程的教程,然后意识到使用指针指向变量,然后使用它来取消引用会使程序更快!
我有基本的汇编知识,但我不明白为什么将变量的地址分配给指针会更快,我们不是在谈论按引用传递或按指针或按值传递!
据我所知,
- 没有指针的代码:内存地址已分配给寄存器
R0
,
就像指针代码中发生的事情一样。
p_int
成为寄存器 R0
的别名,这如何帮助提高程序速度?
不使用指针的代码:
int counter = 0;
int main() {
while (counter < 6) {
++(counter);
}
return 0;
}
那么程序集就像
相反,这里是带指针的代码:
int counter = 0;
int main() {
int *p;
p = &counter;
while (*p < 6) {
++(*p);
}
return 0;
}
那么程序集就像
更新
我联系了课程创建者,他很乐意为我重播和分解课程,为了帮助可能遇到同样问题的其他人,我会留下问题和答案
To access a variable in memory, the CPU needs the address of this
variable in one of the registers. At the lowest levels of code
optimization, the compiler loads this address from the code memory
before each and every access to the variable. The pointer speeds
this up, because being a local variable inside the main() function is
allocated to a register. This means that the address sits in a
register (R0 in this case) and does not need to be loaded and
re-loaded into a register each time. At higher levels of optimization
the compiler generates a more sensible code and the code without the
pointer is as fast as with the pointer. --MMS
正好相反(几乎相同,但多了一条指令:):
编译器的任何在优化级别之间变化的行为都是特定于实现的。因此,尽管向您展示了一些可能违反直觉的演示,但您不应该被告知这是因果关系。
以不同的方式编写代码可以总是触发性能改进或回归,并且不同的优化级别可以有时导致改变走错路。这应该是显而易见的,但是任何更高优化级别导致更差性能的场景(不是这个例子的情况)都应该被视为编译器的问题。
总的来说:没有理由使用指针会使程序 运行 更快。在没有启用所有优化的情况下讨论程序的性能,就像课程创建者在你的引述中所做的那样,是没有意义的。这当然不是改变你编写代码方式的理由。
另一个经常使用但已过时的老技巧是将此类循环编写为递减计数而不是递增计数,因为与零进行比较通常比与值进行比较更快。但这也不应该影响您编写代码的方式,因为现代编译器可以为您进行优化。
程序员应该做的,写课程的人应该教的,就是把代码写得尽可能通俗易懂。这意味着你的两个例子都很糟糕,因为它们不必要地晦涩难懂,而且是 "pre-mature optimization" 的例子。更好的代码是:
int counter;
...
for(counter=0; counter < 6; counter++)
{}
这与代码的可读性差不多,没有理由相信上面的代码在任何已知系统上的性能都会比您的示例差。
这样做:
- 尽可能编写最易读的代码。
- 在发布中,启用优化。
- 如果有性能问题,进行基准测试并找出瓶颈。
- 如果需要,手动优化瓶颈。可能考虑到特定的系统。
原更新提供了很好的答案。另外,原来"counter"是一个全局变量,所以在ARM芯片上每次访问都需要先把这个变量加载到一个寄存器中。根据变量所在的位置和优化级别,这至少是一个 LDR 指令(可能更多),然后更新计数器 ++ 需要添加指令并写回全局变量。
如果将计数器声明为局部变量,那么实际上,使用指针版本并不是最佳选择。在那种情况下,大多数编译器会将计数器分配到一个寄存器中,然后访问它会非常快。如果使用指针,计数器将被强制分配到堆栈(因为它的地址分配给 "p"),并且需要更多的指令来进行加法和访问。
我正在学习有关嵌入式 C 编程的教程,然后意识到使用指针指向变量,然后使用它来取消引用会使程序更快!
我有基本的汇编知识,但我不明白为什么将变量的地址分配给指针会更快,我们不是在谈论按引用传递或按指针或按值传递!
据我所知,
- 没有指针的代码:内存地址已分配给寄存器
R0
, 就像指针代码中发生的事情一样。 p_int
成为寄存器R0
的别名,这如何帮助提高程序速度?
不使用指针的代码:
int counter = 0;
int main() {
while (counter < 6) {
++(counter);
}
return 0;
}
那么程序集就像
相反,这里是带指针的代码:
int counter = 0;
int main() {
int *p;
p = &counter;
while (*p < 6) {
++(*p);
}
return 0;
}
那么程序集就像
更新
我联系了课程创建者,他很乐意为我重播和分解课程,为了帮助可能遇到同样问题的其他人,我会留下问题和答案
To access a variable in memory, the CPU needs the address of this variable in one of the registers. At the lowest levels of code optimization, the compiler loads this address from the code memory before each and every access to the variable. The pointer speeds this up, because being a local variable inside the main() function is allocated to a register. This means that the address sits in a register (R0 in this case) and does not need to be loaded and re-loaded into a register each time. At higher levels of optimization the compiler generates a more sensible code and the code without the pointer is as fast as with the pointer. --MMS
正好相反(几乎相同,但多了一条指令:):
编译器的任何在优化级别之间变化的行为都是特定于实现的。因此,尽管向您展示了一些可能违反直觉的演示,但您不应该被告知这是因果关系。
以不同的方式编写代码可以总是触发性能改进或回归,并且不同的优化级别可以有时导致改变走错路。这应该是显而易见的,但是任何更高优化级别导致更差性能的场景(不是这个例子的情况)都应该被视为编译器的问题。
总的来说:没有理由使用指针会使程序 运行 更快。在没有启用所有优化的情况下讨论程序的性能,就像课程创建者在你的引述中所做的那样,是没有意义的。这当然不是改变你编写代码方式的理由。
另一个经常使用但已过时的老技巧是将此类循环编写为递减计数而不是递增计数,因为与零进行比较通常比与值进行比较更快。但这也不应该影响您编写代码的方式,因为现代编译器可以为您进行优化。
程序员应该做的,写课程的人应该教的,就是把代码写得尽可能通俗易懂。这意味着你的两个例子都很糟糕,因为它们不必要地晦涩难懂,而且是 "pre-mature optimization" 的例子。更好的代码是:
int counter;
...
for(counter=0; counter < 6; counter++)
{}
这与代码的可读性差不多,没有理由相信上面的代码在任何已知系统上的性能都会比您的示例差。
这样做:
- 尽可能编写最易读的代码。
- 在发布中,启用优化。
- 如果有性能问题,进行基准测试并找出瓶颈。
- 如果需要,手动优化瓶颈。可能考虑到特定的系统。
原更新提供了很好的答案。另外,原来"counter"是一个全局变量,所以在ARM芯片上每次访问都需要先把这个变量加载到一个寄存器中。根据变量所在的位置和优化级别,这至少是一个 LDR 指令(可能更多),然后更新计数器 ++ 需要添加指令并写回全局变量。
如果将计数器声明为局部变量,那么实际上,使用指针版本并不是最佳选择。在那种情况下,大多数编译器会将计数器分配到一个寄存器中,然后访问它会非常快。如果使用指针,计数器将被强制分配到堆栈(因为它的地址分配给 "p"),并且需要更多的指令来进行加法和访问。