C++如何确定是否开启优化?开启了什么优化?
假设在一个黑箱环境(比如OJ)中写C++代码,无法查看是否开启O2或O3等优化,可以用什么语句获取优化信息?
比如可以在程序中写这样一句开启优化:
#pragma GCC optimize(3)
但是无法确定原先环境是否开启了优化,开启了什么级别的优化,也无法确定手动开启是否成功,这是这个问题产生的来源。
根据 @CuKing 和 @KalznAsawind 的回答,“是否开启优化”已经解决,但“开启了O2还是O3优化”这一问题仍有待解决。
编译参数可以设置。
例如,开启c++11和o2。
g++ -std=c++11 -O2 main.cpp -o main.out
可以查看OJ的编译指令。看看有没有开启。
但是在程序中应该是没办法获取优化情况的。因为编译优化在g++执行编译完成后就结束了。然后OJ才开始运行编译产物,此时待测程序根本无法获悉编译过程的情况。
不过不排除用什么奇淫技巧的可能
话说题主是准备写oj吗?
利用有符号溢出是未定义行为:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int judge()
{
int x=rand()+1;
if(x<0)x=0;
x+=2147483647;
return x>0;
}
int main()
{
srand(time(0));
printf("%d\
",judge());
}
假如不开优化,那么x至少是1,加上2147483647之后必然溢出成负数,因此返回0.
假如开优化,那么编译器假设不会溢出,此时x非负,非负加正得正,于是编译期直接把judge优化成return 1;了
免责声明:因为是未定义行为,用的时候出现意外情况,我概不负责。
我和 @KalznAsawind 想的差不多,如果判题机没有做额外处理,你应该是成功开启了O3优化的,不过很多判题机都禁止了系统函数以及一些预编译指令或者利用正则直接去掉了相关指令,比如洛谷之类的OJ,所以并不能完全肯定是否开启了O3。
直接利用UB这个判断我感觉不是很行,并且我感觉判断程序是否开启O2或者O3优化本身没有太大意义。
开了O3优化的性能可能并不会比O2快,甚至会更慢,而且O3优化比较激进,程序的逻辑很可能会被改变从而导致错误行为,一般除了性能测试应该使用不到这玩意儿。
最好的方式就是去github找一些开源oj的判题机,看看他们是怎么处理的,比如hustoj,qingdao oj等等。
__OPTIMIZE__
__OPTIMIZE_SIZE__
__NO_INLINE__
这三个宏可以检测是否有优化,是否使用-Os
、-fno-inline
,只要你用的不是msvc。
确定优化等级,尤其是区分-O3
与-O2
,因为各个编译器相同优化等级提供、启用了不同的pass,同编译器不同版本之间启用的pass也有可能不同,而不存在确定的检测方法。实在要在黑箱环境内检测的话,感觉只能事前观察同版本的相同编译器产物,针对性寻找特征。同时,统计执行时间差异也是可行手段。