代码改变世界

软件呓语:安迪-比尔定律的背后(上)

2010-06-27 06:28  Ivony...  阅读(4111)  评论(12编辑  收藏  举报

首先恭喜博客园娱乐事件又出现了新的话题,某人总是能在大家基本快要淡忘的时候在首页扔下一坨,呃,那啥。

这一次除了一如既往的提供低级错误以供娱乐之外。还引出了一个IT界的恶魔:“安迪-比尔定律”。

 

先来补习一下安迪-比尔定律是什么:安迪和比尔是两个人,他们的财产多的我必须让我的收入按几何速度增长才能追得上。没错,他们就是Intel和Microsoft的掌门人(曾经是)。嗯,邪恶的Wintel联盟。安迪-比尔定律的简单描述就是,安迪提供什么,比尔拿走什么。计算机的硬件遵循着摩尔定律在沿几何速度增长的同时,软件却会降低自己的性能把这些增长全部消化掉。

 

好吧,这是一个邪恶的定律,很多人(如某)认为是邪恶的比尔大叔为了保证他和安迪能永远呆在富豪榜上密谋的结果。这么说也有几分道理,否则为什么我们现在的软件还是这个样子(无聊的窗口和任务栏),好像并没有感受到几何速度增长的快感。

这个问题困扰了我很长一段时间,也曾有一段时间,我抛开了这个问题,好吧,这就是邪恶的比尔大叔干的好事,让我们无法用到与硬件相称的功能的软件。但这个世界上并不是只有比尔大叔而已,还有乔布斯大叔、埃里森大叔等等等等。显然这些人并没有被安迪或者比尔绑架妻儿,软件业看起来还是一个竞争充分而且健康的行业。显然,比尔是恶魔只是回避问题的人们杜撰的神话。我必须正视它,并试图找出背后的原因,揪出暗处的恶魔。

 

那么,更快的CPU、更大的内存,他们所带来的优势到底被什么吞噬了?这个问题是如此复杂,以至于在我自以为找到了正确答案很久以后,,,,都没想过去公开的讨论这个问题,以免被不长眼的板砖拍死。

显然大家并不喜欢听我一直这样废话,下面就进入正题。需强调的是,仅代表个人观点。

 

 

我们来考虑一个最简单的例子,假设现在有一台机器,其作用是做两个整数的加法运算,它有输入单元用于接收参与运算的两个整数,有输出单元用于输出结果,有计算单元来计算以及暂存单元来存放中间结果。由于是机器,所以所有的这些部件都可能出错,输入单元可能会把1识别为7,输出单元也可能少输出一个0,当然计算单元也可能会算出1+1=3。好在它们出错的概率都很低很低,至少在一个人们可以接受的范围。

现在人们不满足于两个数值相加的简单需求,人们希望这台机器可以完成三个数值的相加,我想,你会认为功能只是增加了一倍,或者一半。的确如此,如果我们每一个步骤所花费的时间都是一样的,那么再计算两个数值相加的时候,输入两个数(2)+计算一次(1)+输出一次(1)=四个时间单位,计算三个数的时候,输入三个数(3)+计算两次(2)+输出一次(1)=六个时间单位。对哦,性能应该顶多下降50%才是。

 

但问题的关键在于!对于这个机器出错的概率来说,又是怎样的情况?

为了得到这个结果,我们不妨假设所有的单元出错的概率都是1%。那么首先我们算算,完成两个数值相加的过程出错的概率是多大?

 

为了计算两个数值的相加,输入单元要接收两个数值,其中每接收一个数值,有1%的机会搞错,导致结果错误。那么,接收第一个数值出错的概率是1%,正确的概率是99%,但在正确的99%中,又有1%概率把第二个数搞错。所以最终正确的概率是99%*99% = 98.01%

接下来进入计算单元,得到一个错误的结果的可能是1%,意味着输入单元正常工作的情况下,仍有1%的概率出错,所以得到正确结果的概率为:98.01% – 98.01% * 1% = 97.0299%,约为97.03%。

最后,即使计算单元正确,最终的输出单元也可能抽风把1输出成2,这个概率也是1%,现在这台机器正常工作的概率约为96.06%。

如果人们可以接受的错误率是5%,那么现在这台机器还在人们可以容忍的范畴内。那么我们增加一半的功能,即计算三个数值的和的话,会怎样?

这里就只简短的演算一次了,首先是输入单元输入三个数值,正确率:97.03%,计算单元计算两次,正确率:95.1%,输出单元也有1%概率抽风,最后正确率是:94.1%

这时候,这机器出错的概率超出了人们可以容忍的范畴了。。。。。

 

如何解决这个问题?勤劳智慧的劳动人民很快就想到了解决方案:计算两次,如果结果相同,才认可这个结果。

这样,为了得到一个正确的结果,我们不得不花费双倍的开销,即现在至少需要十二个时间单位(所以性能下降了三倍而不是一半),才能确保我们得到可以接受的正确的计算结果。并且,如果第一次计算出现错误(5.9%),那么我们还需要两次以上的计算才能得到正确的结果。。。。很明显,性能的下滑速度要比功能的增长速度快得多

 

当然,两次计算可以极大的提高准确率,使得我们在计算三个四个或是五个数相加的时候,两次计算的准确率也够用了。但是,当计算的数超过一个限度的时候,我们又会需要三次计算、四次计算才能确保计算的正确率了。。。

 

现在只是考虑了加法的情况,当我们引入乘法的时候,又要编写新的程序,新的程序会给运算单元更大的出错的概率。为了保证出错概率在可容忍的范围,人们又不得不浪费性能去增强健壮度,但是,软件复杂度增加所带来的问题,比这更复杂,也更严重。。。。