C++ 我什么时候可以自信地用-O3编译程序?
我见过很多人抱怨C++ 我什么时候可以自信地用-O3编译程序?,c++,gcc,compiler-construction,compilation,C++,Gcc,Compiler Construction,Compilation,我见过很多人抱怨-O3选项: 我查看GCC中的手册: 我还确认了代码,以确保两个选项是-O3上包含的唯一两个优化: if (optimize >= 3){ flag_inline_functions = 1; flag_rename_registers = 1; } 对于这两种优化: -finline函数在某些情况下很有用(主要是在C++中),因为它允许我们使用-finline限制定义内联函数的大小(默认为600)。当设置较高的内联限制时,编译器可能会报告一个错
-O3
选项:
-O3
上包含的唯一两个优化:
if (optimize >= 3){
flag_inline_functions = 1;
flag_rename_registers = 1;
}
对于这两种优化:
在某些情况下很有用(主要是在C++中),因为它允许我们使用-finline限制定义内联函数的大小(默认为600)。当设置较高的内联限制时,编译器可能会报告一个错误,抱怨内存不足-finline函数
通过使用寄存器分配后剩余的寄存器,尝试避免计划代码中的错误依赖。这种优化将最有利于具有大量寄存器的处理器-frename寄存器
-finline函数
可能会引入严重的缓存惩罚,甚至比-O2更慢。我认为缓存惩罚不仅仅取决于程序本身
对于重命名寄存器,我认为它不会对x86这样的cisc体系结构产生任何积极影响
我的问题有2.5个部分:
-O3
选项?我想这两种优化,特别是重命名寄存器,可能会导致与-O0/O2不同的行为。我看到一些用-O3
编译的程序在执行过程中崩溃了,这是确定的吗?如果我只运行一次可执行文件而没有任何崩溃,这是否意味着使用-O3
是安全的
编辑:确定性与优化无关,它是一个多线程问题。然而,对于一个多线程程序,当我们运行一次没有错误的可执行文件时,使用-O3
是不安全的。David Hammen指出,-O3
对浮点运算的优化可能会违反严格的弱排序标准进行比较当我们想使用-O3
选项时,是否还有其他需要注意的问题?
-O3
和-O2
之间进行更改。是否有任何常规方法来决定我是否可以通过-O3
获得性能改进?例如,更多寄存器、短内联函数等[已回答]
编辑:Louen对第三部分的回答是“平台的多样性使关于这个问题的一般推理变得不可能”当评估-O3
的性能增益时,我们必须尝试这两种方法,并对我们的代码进行基准测试,以确定哪一种更快
在浮点寄存器的精度高于double的机器上,浮点操作可能会导致奇怪的行为。比如说,
void add (double a, double b, double & result) {
double temp = a + b;
result = temp;
if (result != temp) {
throw FunkyAdditionError (temp);
}
}
编译一个使用未优化的add
函数的程序,您可能永远不会看到任何FunkyAdditionError
异常。编译优化后,某些输入会突然启动,导致这些异常。问题是,在进行优化时,编译器将temp
作为一个寄存器,而result
作为一个引用,不会编译到寄存器中。添加一个内联
限定符,当使用-O3
编译编译器时,这些异常可能会消失,因为现在结果
也可以是寄存器。关于浮点运算的优化可能是一个棘手的问题
最后,让我们看看其中一个例子,当一个程序用-O3编译时,事情确实在夜间发生了碰撞。问题只出现在-O3中,因为编译器可能内联了distance
函数,但在扩展精度浮点寄存器中保留了一个(但不是两个)结果。通过这种优化,c
void add (double a, double b, double & result) {
double temp = a + b;
result = temp;
if (result != temp) {
throw FunkyAdditionError (temp);
}
}