实测!!论如何在OI赛场上提高程序运行速度

实测!!论如何在OI赛场上提高程序运行速度

摘要:其实register、inline和读入优化大多数情况下并没有什么卵用,,

目录:

1.引子

2.实验机基本信息

3.inline关键字测试

4.register关键字测试

5.cin、scanf、快读三种读入方式的比较

6.附:for循环中++i与i++两种写法的速度测试

7.总结

 

引子:

据说变量前面加个register

以及函数前面加个inline

以及写个读优啥的

(PS:我知道我很弱请不要吐槽我的读优)

能够提高程序运行速度!!

天真的我竟然相信了!!

于是养成了一些不好的习惯,比如变量前面顺手加个register,函数前面顺手加个inline以及顺手写个读优啥的……

于是遭到了诸如hzwDLszjDL的嘲讽……

所以,rigister、inline和读优到底有没有用呢??

今天我们一起来做一个实验!!!!!

--------------------------华丽的分割线--------------------------

实验机基本信息:

测试系统:Mac OS

型号:MacBook Air 7, 2

处理器:Inter Core i5  双核 1.6GHz

L2:256KB  L3:3MB

运存:8GB

 

inline关键字测试

inline是什么东西?据说是内联函数。

我管他是什么,我只需要知道他快不快就行了。

那我们就找一个函数做实验吧。比如……用快读函数做实验怎么样??

我们首先随机生成一个数据规模一个亿的测试数据。

妈耶……竟然1.5个G,不可思议……

码一个快读。

测试!还行,总用时1min3.744s(运行的时候我还以为我电脑死了)

那么接下来我们加一个inline

1min3.878s!呵呵哒!似乎更慢了!

这是神马情况????

于是查了一下百度百科……据说直接用inline的话,编译器不会鸟你,你需要在头文件里声明一下……

我写的程序编译的时候竟然还要看编译器心情??

行吧,你说啥就是啥。那我就在前面声明一下。

运行!!!!!

窝草!!!!!奇迹发生了!!!竟然快了1秒!!!!

看来inline还是有那么一点用的。

但是inline在任何时候都有用吗????

我们在写一个简单的函数试一试。先不加inline。

为了让实验效果更明显,我们把循环次数加到10个亿

这个函数可以说是已经简单地不能再简单了。

测试!

2.4s,还行。

那么加inline呢??吸取读优的经验,先在前面声明一下

足足慢了0.2毫秒!!!

实验结果实验1实验2
不加inline1min3.744s2.498s
加inline,不声明1min3.878s——
加inline,并声明1min2.432s2.677s

小结:看来inline这个东西还是挺玄学的,读优用用就算了,其他函数还是别随便加了,免得帮倒忙。

 

register关键字测试:

register是什么?据说是强调变量将被频繁使用,央求CPU在运行的时候把这个变量放到寄存器里,以加快后期的访问速度。

你是谁啊,CPU凭啥鸟你啊

为了实验更加简单,我们直接用for循环测试吧。

为了实验效果更加明显,我们直接上一个一百亿的大循环。

其实我一开始用的是int,结果硬是半天跑不完。后来才意识到int类型已经溢出变成负数了……

运行。

还行,用了23秒。

那么我们把register加上。

屁用没有,还更慢了!

实验结果实验1
不加register23.370s
加register23.455s

小结:你要是觉得register好看你就加吧,反正他并没有什么用。因为CPU并不想鸟你。

 

cin、scanf和快读三种读入方式的比较

我们依然使用刚才生成的test.in文件

为了cin不会被虐的太惨,这次我们只读入前一千万个数据。

首先是被很多人嫌弃的cin。让我们来共睹他的风采

用时44秒。不错,数字很吉利。已经预示了他的结局。

接下来是编者最喜欢的scanf

用时2.2秒,完虐cin!!!!

那么接下来……有请大名鼎鼎的快读……

结果还用问吗,肯定完虐scanf啊

六秒???开玩笑吗??快读你也太不给力了吧!!??

不行不行。快读怎么能输呢……

让我们来分析一下原因

可能是由于数据时随机生成的,数字普遍较大,位数较多。而快读是逐位读取,这样无形之中常数会变得很大

这样吧,我们重新生成一个数据,让所有数字大小均在100以内。

硬盘瞬间腾出一个G的内存

这次我们只生成一千万规模的数据

这样常数就应该小很多了吧

这次我们只比较scanf和快读。(cin已经没有可比性了)

我们先来看scanf

用时1.9秒,还行

那么快读呢????(快读给力一点啊)

呵    呵     哒

实验结果实验1实验2
cin44.248s——
scanf2.220s1.939s
快读6.259s2.588s

小结:同志们,别指望快读了。快乖乖用scanf吧。

 

附:for循环中++i与i++两种写法的速度测试:

++i和i++的区别相信大多数码农都知道。++i是先加后赋值,i++是先赋值后加。

但是对于for循环中的++i或者i++似乎并没有什么区别,因为他并不需要赋值。

那么在速度上他们有区别吗?

还真有!!!

据说,在执行程序的时候,++i是直接把变量+1,而i++需要先把变量i复制到另一个内存空间,在另一个内存空间中+1,然后再复制回来。所以,理论上++i是比i++要快的。

呵呵哒,inline和register理论上加了还比不加快呢

为了验证理论和现实的差距,我们一起来实践一下

我们来一个十亿的for循环,先看++i的

然后是i++

确实快了一丢丢,但是差别并不是很大。

小结:真正赛场上for循环中的++i和i++其实都差不多,++i虽然比i++快一点点,但就这么一点数据规模看不出什么太大的优势。

 

总结:

实验做完了,总结一下吧。

多数情况下不加inline比加inline快。

register加上屁用没有,还增加代码量。

scanf战胜了cin和快读。

for循环中++i比i++稍快一点点。

当然,我做的实验违反了多次实验的原则,各位可以在线下做一做这个无聊的实验

所以,oi赛场上如何提高程序运行速率??

踏实写代码,别搞花里胡哨的东西!

其实主要看人品。

本文章为原创,转载请注明出处。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值