程序玄学常数优化
Posted unnamed05
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序玄学常数优化相关的知识,希望对你有一定的参考价值。
一、读入优化
读入时的速度cin<scanf<getchar
我们可以用getchar()读入整数
inline int read(){ int num=0; char c; while(isspace(c=get_char())); while(num=num*10+c-48,isdigit(c=get_char())); return num; }
fread是直接对二进制文件进行读入,速度更快
const int MAXBUF = 100000; char buf[MAXBUF], *ps = buf, *pe = buf+1; inline void rnext() { if(++ps == pe) pe = (ps = buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin); } template <class T> inline bool in(T &ans) { ans = 0; T f = 1; if(ps == pe) return false;//EOF do{ rnext(); if(‘-‘ == *ps) f = -1; }while(!isdigit(*ps) && ps != pe); if(ps == pe) return false;//EOF do { ans = ans*10+*ps-48; rnext(); }while(isdigit(*ps) && ps != pe); ans *= f; return true; }
二、运算优化
1、位运算优化:乘上2的幂或除以2的幂时可以直接用位运算进行优化
2、除法、取模优化:除法运算的耗时是乘法运算的几倍,能不用尽量不用,比如i/a>b可以以换成i>a*b
3、浮点数除法优化:
float a,b,c; init(a,b,c); a/=c; b/=c;
可以换成
float a,b,c; init(a,b,c); float d=1/c; a*=d; c*=d;
三、针对cpu缓存的优化
1、一维数组的数组大小尽量开成2的幂,高维数组每一维的数组大小最好都不要开成2的幂!(状压dp时要尤其注意)
2、遍历数组时最好按数组存放顺序遍历
For example
//first
for(int i=0;i<n;i++) for(int j=0;j<m;j++) a[i][j]*=2;
//second
for(int i=0;i<m;i++) for(int j=0;j<n;j++) a[j][i]*=2;
第一种比第二种效率快得多
3、数组的索引也是需要时间的,特别是高位数组的索引寻地址效率很低,因此我们可以用指针来代替数组寻址
//first int a[55][65][75][85]; int main() { int *p=&a[0][0][0][0]; for(int i1=0;i1<55;i1++) for(int i2=0;i2<65;i2++) for(int i3=0;i3<75;i3++) for(int i4=0;i4<85;i4++) (*(p++))++; } //second int a[55][65][75][85]; int main() { for(int i1=0;i1<55;i1++) { int (*p)[65][75][85]=a[i1]; for(int i2=0;i2<65;i2++) for(int i3=0;i3<75;i3++) for(int i4=0;i4<85;i4++) p[i2][i3][i4]++; } } //third int a[55][65][75][85]; int main() { for(int i1=0;i1<55;i1++) for(int i2=0;i2<65;i2++) for(int i3=0;i3<75;i3++) for(int i4=0;i4<85;i4++) a[i1][i2][i3][i4]++ }
很明显,效率上第一种>第二种>第三种,但很多时候并不是单纯的按顺序访问数组,这种时候第二种写法(只需要对3维数组寻址)就派上用场了
3、循环展开
举一个很蠢的例子
int cnt=0; for(int i=0;i<n;i++) cnt++;
int cnt1=0,cnt2=0,cnt3=0,cnt4=0; for(int i=0;i<n;i+=4) cnt1++,cnt2++,cnt3++,cnt4++; int cnt=cnt1+cnt2+cnt3+cnt4;
第二种的效率是是一种的4倍
这里有两点需要注意的
(1)循环展开一般最多展开8重,再多的话反而会使效率降低
(2)循环展开的各条语句一定要是无关的,比如
int cnt=0; for(int i=0;i<n;i+=4) cnt++,cnt++,cnt++,cnt++;
这样写效率没有显著提升(因为4条语句都要用到cnt,4条语句相关)
以上是关于程序玄学常数优化的主要内容,如果未能解决你的问题,请参考以下文章