C++ 微优化:使用局部变量与类成员进行迭代
我想如果我将迭代变量声明为类成员一次,我会节省一些时间:C++ 微优化:使用局部变量与类成员进行迭代,c++,micro-optimization,C++,Micro Optimization,我想如果我将迭代变量声明为类成员一次,我会节省一些时间: struct Foo { int i; void method1() { for(i=0; i<A; ++i) ... } void method2() { for(i=0; i<B; ++i) ... } } foo; 你能解释一下性能差异吗 (我需要在Arduino上运行许多简单的并行“过程”,这样的微优化会产生不同。)当您在循环中声明循环变量时,它的范围非常狭窄。编译器可以随时将其保
struct Foo {
int i;
void method1() {
for(i=0; i<A; ++i) ...
}
void method2() {
for(i=0; i<B; ++i) ...
}
} foo;
你能解释一下性能差异吗
(我需要在Arduino上运行许多简单的并行“过程”,这样的微优化会产生不同。)当您在循环中声明循环变量时,它的范围非常狭窄。编译器可以随时将其保存在寄存器中,因此它不会被提交到内存中,甚至一次也不会
当您将循环变量声明为实例变量时,编译器没有这种灵活性。它必须将变量保存在内存中,以防某些方法需要检查其状态。例如,如果您在第一个代码示例中这样做
void method2() {
for(i=0; i<B; ++i) { method3(); }
}
void method3() {
printf("%d\n", i);
}
void方法2(){
对于(i=0;i
你能解释一下性能差异吗
对于这种性能差异,我能给出的最合理的解释是:
数据成员i
在全局内存上声明,全局内存不能一直保存在寄存器中,因此,由于范围非常广泛,对它的操作将比对循环变量i
的操作慢得多(数据成员i
必须满足类的所有成员函数)
@达里奥补充道:
此外,编译器不能自由地将其临时存储在
注册,因为method3()
可能会抛出异常离开对象
处于不想要的状态(因为理论上没有人阻止你
写
int k=this->i;for(k=0;ki=k;
。该代码
将几乎和局部变量一样快,但必须保持
当method3()
抛出时的帐户(我相信在有保证的情况下)
不抛出编译器将使用-O3
或-O4
对其进行优化
(已核实)
“如果我将迭代变量声明为类成员一次,将节省一些时间”这是一个非常奇怪的想法。每次都是this->i
。我会冒险猜测局部计数器变量只存储在寄存器中,但要知道这些事情,请使用-save temp
编译并查看程序集。A
和B
是否小于256?那么编译器可能是able在本地情况下使用8位int(在8位MCU上更快)。这一切都是猜测。其想法不是分配额外的堆栈空间和每次调用保存一条指令。..
做许多不同的事情,但i
用作低于256(字节大小)的数组索引。此外,编译器不能将其临时存储在寄存器中,因为method3()
可能引发异常,使对象处于不需要的状态(因为理论上没有人阻止您写入int k=this->i;)(k=0;ki=k;
该代码的速度几乎与局部变量一样快,但当method3抛出时,您必须考虑到这一点(我相信当有保证它不会抛出时,编译器将使用-O3或-O4对其进行优化。待验证抱歉:)我不想纠正你。我习惯于在答案中添加我的想法,只是因为我喜欢写关于编程的文章。顺便说一句,快速响应+1:为(register int I=0;…)声明是个好主意吗
然后呢?假设C++11之前的标准,其中寄存器
说明符没有被弃用。它被弃用是有原因的,原因是它在今天完全无用。
void loop() { // Arduino loops
foo.method1();
foo.method2();
}
void method2() {
for(i=0; i<B; ++i) { method3(); }
}
void method3() {
printf("%d\n", i);
}