转:任务切换有害论

书摘,来自《软件随想录》,Joel Spolsky

在管理一个程序团队时,第一件要学的事就是任务配置(task allocation)要正确。「任务配置」只是把事情分给大家做的夸大说法。用希伯来文的普通话来说就是「倒文件」(因为你会把文件倒在某人身上)。有些事情做得对会得到不可思议的生产力利益,决定哪些文件要倒在谁身上就是其中之一。反过来没做好的话可能就会陷入麻烦的状况,没有人能做好何任何事情而且大家都抱怨「在这里什么事都做不起来。」

由于这是个针对程序员的网站,我要拿个程序设计问题让你的脑袋动一动暖暖身。

假设你有A和B两件运算要做。每一件都需10秒的CPU时间。现在你有一颗CPU,为了简化问题,所以工作序列中没有其他东西。

在我们的CPU中可以选择是否用多工处理。所以你可以先做好一件再做另一件。

循序处理

运算A
1 2 3 4 5 6 7 8 9 10
运算B
11 12 13 14 15 16 17 18 19 20

也可以使用多工方式。如果用多工的话可以假设这颗特别的CPU每个工作每次可以执行一秒,而且工作切换完全不花时间。

多工处理

运算A
1 3 5 7 9 11 13 15 17 19
运算B
2 4 6 8 10 12 14 16 18 20

你会选哪一种方式呢?大部份人的直觉反应都认为多工比较好。不管哪一种状况,都得等20秒才能两件运算都完成。不过可以想想单就各件运算来说要多久才有结果。

在两种状况下,运算B(标成蓝色)都要20秒才得到结果。不过运算A的结果在多工时需要19秒。可是循序时就只要10秒就好了。

换句话来说在这个安排好的例子中,循序处理的每件运算的平均时间比多工处理少(15秒对19.5秒)。(事实上这例子也并不是真的那么假 - 它是源于Jared在工作上必须解决的一个真实问题。)

方法 运算A花的时间 运算B花的时间 平均
循序处理 10秒 20秒 15
多工处理 19秒 20秒 19.5

我刚刚说过「工作切换完全不花时间」。其实在真的CPU中工作切换是需要一点点时间的,基本上要足够储存CPU暂存器的状态并载入其他工作的CPU暂存器。实际上这短到几乎可以忽略。不过为了让生活更多乐趣,让我们假设工作切换需要半秒。现在情况变得更糟了:

方法 运算A花的时间 运算B花的时间 平均
循序处理 10秒 20秒 + 1次工作切换 = 20.5秒 15.25
多工处理 19秒 + 18次工作切换 = 28秒 20秒 + 19次工作切换 = 29.5秒 28.75

现在呢,虽然我知道这有点蠢,不过就算为了让我高兴一下,想想如果工作切换需要一分钟拿如何?

方法 运算A花的时间 运算B花的时间 平均
循序处理 10秒 20秒 + 1次工作切换 = 80秒 45秒
多工处理 19秒 + 18次工作切换 = 1099秒 20秒 + 19次工作切换 = 1160秒 几近19分钟!!

工作切换用的时间愈长,多工处理的代价愈大。

这件事本身不怎么新奇,不是吗?不久大概就会有些白痴气愤地写信指控我「反对」多工处理了。他们会质问我:「你真的想要回到那种得先结束WordPerfect才能执行Lotus 1-2-3的DOS时代吗?」

不过那并不是我的意思。我只是想要你同意,在这类例子中:

  • 循序处理会让结果平均上比较快得到,而且
  • 工作切换需要愈久,多工处理所付的代价就愈大。

够了,别管CPU了,来管管人吧,这有趣多了。这里的重点在于管理「程序员」时,工作切换会需要很长很长的时间。因为程序设计这种工作必须同时在脑袋里记很多东西。另外记住的东西愈多,写程序时生产力愈高。用全速写程序的程序员脑里随时都会记住无数的事情:变量名称,数据结构,重要的API,写过常要用到的辅助函数名称,甚至存放源代码的次目录名称,一切东西都要记住。如果你把程序员送到克利特岛去度假三星期,他所有东西通通都会忘掉。人脑似乎会把东西移出短期RAM,改存到永远都读不回来的备份磁带上。

要多久呢?嗯,我的软件公司最近放下手头上在做的事(开发一套代号CityDesk的软件产品),花了三星期去帮助某个客户处理一个紧急状况。当我们回到办公室时,感觉好像要另外三星期才能回复全速制作CityDesk。

就个人层次来说,你曾经注意过某件事吗?叫某人做一个工作可以做得很好,可是如果给他两个工作,他会把其中一个做好却忽略另一个,不然就是两件工作都做得很慢,慢到你觉得懒鬼都比他勤劳。这是因为程序设计的工作就是需要很长的切换时间。就我自己来说,当我需要同时完成两个程序设计项目时,切换时间大概要六个小时。以一天八小时来看,等于说多工处理把我的生产力降到每天只剩二小时。真令人沮丧啊。

同样的道理,如果你给某人两件工作,应该要感谢他们只做一件工作而放弃另一件,因为这样能做好更多的事,而且平均上也能更快完成工作。事实上这一切的重点就是绝对不要让人同时做一件以上的事。请确定你有明白它的意思。好的经理人会认为自己的责任是消除障碍,好让大家都能专注在一件事情并把它真的完成。遇到紧急状况时,请先想想能不能自己处理掉,真的不行再丢给深陷在项目中的程序员吧。