常数优化技巧
前言
在oi中,常数优化可谓极其重要
当然,不只是oi,常数优化一定程度上组成了代码风格
所以说,如何进行常数优化呢?
下面就简单的介绍我常用的几个常数优化技巧
#1习惯使用 const …
const int inf=0x7fffffff;
void exgcd(int a,int b,int &d,int &x,int &y){
if(!b){
d=a;x=1;y=0;return;}
exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
const的最大作用就是减少参数传递的时间。
#2 不要递归!!
用基础算法算法gcd来举例:
void gcd (const int a,const int b){
if(b)return a;
else return gcd(b,a%b);
}
相信很多人习惯于这种写法
但是又一个很严重的问题:在每次递归调用函数的时候,程序都会在栈中新建空间来存放递归函数里的变量,这无疑造成了极大的性能损失,不同于前一个,减少递归而使用迭代能够造成可观的优化。
所以说:
int gcd(int a,int b){
while(b){
int t=a;
a=b;
b=t%b;
}
return a;
}
#3习惯于将变量声明在循环外
定义变量意味着系统在内存条里找出一块地方让你存数据,想想cpu到内存条之间长长的距离 还有你那不怎么好的主板 特别是在使用AMD处理器(非Zen构架)的情况下
所以说对于上面 #2 的程序而言
int gcd(int a,int b){
int t;
while(b){
t=a;
a=b;
b=t%b;
}
return a;
}
这样或许才是更优美的写法
#4 使用 inline
inline可以让你的非递归函数(此函数里不再调用其他函数)编译在原函数中而非另外开栈内存
所以对于 #3 的程序我们可以稍加修改
int gcd(int a,int b){
int t;
while(b){
t=a;
a=b;
b=t%b;
}
return a;
}
int main(){
cout<<gcd(4,8);
return 0;
}
比如在main()中调用
这段代码就相当于
int main(){
int a=4,b=8;
int t;
while(b){
int t=a;
a=b;
b=t%b;
}
cout<<a;
return 0;
}
#5 register
前文中说到,每当你定义一个变量或函数,抑或修改变量维护数据,程序都会不远万里的请内存条帮你完成这项工作,而物理上cpu到内存插槽之间的距离一定程度也影响车cpu和内存交互的速度。
能不能缩短这个距离呢?
直接把变量开在寄存器里不就不用不远万里找内存条了
所以:
for(register int i=1;i<=MAXN;){
i++;
}
要比
for(int i=1;i<=MAXN