可恶的I/O-Bound工作

by admin

I/O-Bound这个词实在不知道该如何翻译成中文,或许我该找本中文的操作系统来看看。它说的是这个意思:

———-科普开始———-

通常来说,一段程序的执行需要几个步骤:从存储器里取出需要操作的数字,然后进行运算,再将结果写入存储器里。就这么简单。

比如说,我们需要计算1+2=_。首先我们需要从存储器里获得1和2这两个数,然后将这两个数进行加法运算,最后再将结构3写入存储器里。

看似平凡的三个步骤,却暗藏着玄机。根据现在的处理器和存储器结构,做一个加法运算的时间大概需要1个周期,而访问一次内存需要的大概是500个周期。这是500倍的差距。这只是读写内存,而对硬盘的读写所需要的时间比内存还要多100,000倍!

程序的差异性就主要体现在它们对处理器和存储器读写的不同需求上。有些程序主要的执行时间花在了处理器的运算上,这些就是CPU-Bound的程序,而有些花在处理器读写(更一般地,输入输出,Input/Output, I/O)上,这就是I/O-Bound。

下面的图可能更形象一些:

IO-Bound

I/O-Bound

CPU-Bound

CPU-Bound

在图中,黑色的块代表处理器在计算,浅色的块代表正在进行I/O读写。

———-科普结束———-

下面进入正题。

这些枯燥的叙述可能还不足以点燃你对I/O-Bound的仇恨,假如它发生在你的生活中呢?

处理器的计算就好比我们办正事,而I/O读写就好比花在路上或者是排队的时间。假设你要拍毕业证了照片了,而学院的老师以管理小学生的办法要求你们明天上午9点集合,统一拍照。好吧,第二天你起晚了,到了指定的地点发现已经有一长串的队伍拍在那里了。你等啊等,不时拿出手机上会儿网,和同学聊会儿天,看看美女,再骂两句前面插队的人,在排了两个小时的队后,终于轮到你了。你刚端坐在椅子上,还想再调整一下姿势,只见闪光灯一闪,然后就听到一个似曾相识的声音:“下一个!”

拍照的时间不到一分钟,你却等了2个小时,先别急着骂街。你花在排队等待的时间只是办正事时间的120倍而已,想一想CPU同学,每时每刻都在忍受这大于500倍的I/O-Bound程序还这么任劳任怨,真是精神可嘉。只可惜CPU是老外发明的,要不然它早就获得五一劳动奖章了。

类似这样的事情每天都在发生,我们的时间,甚至生命每时每刻都在被浪费着。今天我去上海办签证,真正递送签证的时间也就只有15分钟,但我从早晨8点出门,晚上8点才回来。其他时间都花在排队买票、等车、坐车、认路上了。这个时间差距也足有48倍。

认清了I/O-Bound工作的真实面目,你一定像我一样深深地恨上它了吧。彻底摆平它是不大可能的,我们只能尽可能使它浪费的时间减小的最少。如何做到呢?先让我们来看看计算机设计者们是如何做的,因为他们也同样痛恨I/O-Bound的工作。

最土最暴力的方法就是减少I/O操作的时间,比如减少访问存储器所需要的时间。但这种提升空间毕竟有限而且成本昂贵。我们也可以这样做,下次去上海的时候就直接打的,这样就省去认路、买票、等车的时间了。这样做需要付出的代价也是极大的,可能就是你接下去几个星期就要啃馒头了。

还有一种方法就是利用时空的局限性,顺便帮别人也把事办了。计算机中的缓存(Cache)就是基于这种考虑设计的,取一个操作数的时候,顺便把其他操作数也取到了,而且以后再用到的时候就不用再花时间取了。当然,聪明的我们也在用着这种方法,只是不知道而已。你去食堂吃饭的时候,同学经常让你帮他们打包,你就在无形中减少着他们因为I/O-Bound所浪费的时间——至少,他们不用再去食堂、排队、打饭、找座位了。而且还可以为自己攒人品哦。你要是顺便再多打一份,留着晚饭吃(如果不嫌凉的话)就更像缓存的行为了。

多程序调度

多程序调度

一种最上档次方法就是同时进行多任务。对处理器来说,它可以在等待一个程序I/O操作的同时为另一个程序做运算,就像右图。这样,处理器可以说”随时都在办正事“,并没有浪费时间。当然,这需要巧妙的调度。我么当然也可以做到,甚至已经做到了。当我们排长队或者坐车的时候,我们可以做一些”CPU-Bound“的工作,比如读读论文、看看闲书、和女朋友煲电话粥、和旁边美女搭个讪等等。充分利用时间,决不让它无故地浪费。

可惜我一个都做不到,一坐上车,就浑身不舒服。只能听听京剧,然后就睡着了。

本文所有图片来自这里