Hadoop背后的数学

自从Nathan Marz同学写了那篇著名的How to beat the CAP theorem的Blog,以及Storm发布之后,俨然成为了技术界新偶像。顺着他本人的blog,翻了一下他过去几年的写的技术文章,发现老美的牛人们都爱总结,能够把技术实践提升到理论高度,然后抽象出新的设计和产品,比起我等只能每天苦逼苦逼应对实际需求的人来说,还是强出很多。我自己觉得那么多年,虽然觉得做什么都能做了,但是现在还是只能谈到模仿,做不到提炼总结和超越。

和著名的CAP的那篇Blog,Nathan Marz还有很多其他非常有料值得一读的博客,与其在国内的各种Hadoop大会上听大家泛泛而谈架构,还不如多看看老外们总结下来的技术博呢,比如这篇The mathematics behind Hadoop-based systems,比起大家简单列列机器数字来说,有价值得多。

我曾经写过,数学对于称为一名优秀的程序员是很重要的,但这不一定意味着一定要是多高深的数学。Nathan的这篇Blog用到的数学只有初中难度,但是的确写明白了我们遇到的很多Estimation以及集群数量预估的实际问题,我想一定也有很多人用hadoop但是和我们一样,对于很多机器数量或者workflow的管理是很粗放的,相信这篇blog对很多人都会有用,所以把它翻译成中文,全文如下


基于Hadoop的系统背后的数学

我希望一年之前我就知道这些。现在,根据一些简单的数学,我就可以回答:

  • 为什么在我将处理能力翻倍之后,我的workflow的速度没有翻倍?
  • 为什么10%的任务失败率会导致我的运行时间上升到原来的300%?
  • 如果通过优化了我的workflow的运行时间的30%导致运行时间下降了80%?
  • 我的集群中到底需要多少机器可以满足性能和容错的需要?

所有这些问题都可以通过这样一个简单的等式干净地回答:

运行时间(Runtime) = 额外开销(Overhead) / (1-{处理一小时数据需要的时间})

我们很快就可以推导出这个等式。首先,让我们简单地讨论一下什么是我所说的“基于Hadoop的系统”1。Hadoop的一个常见的用例,就是通过运行一个workflow来处理来连续进入的流数据。这个工作流运行一个”while(true)”的循环,然后每个workflow的迭代,都处理自从上个迭代依赖累积的数据。

下面的这些分析的灵感可以在一个简单的示例中概括出来。假如说你有一个workflow需要运行12小时,然后它会在每个迭代中处理12个小时的数据。然后假如说你加强了这个workflow去做一些额外的分析,然后你估计你在当前的这个workflow中需要多花两个小时来处理。然后麻烦来了。你的workflow增加的运行时间可能远超过两小时。它可能增加了10个小时,100个小时,或者这个workflow可能呈螺旋式上升地在每个迭代中花费越来越多的时间知道无限。

为什么?

问题在于,你将处理12个小时数据的workflow的运行时间增加到了14个小时。这意味着当下一次workflow运行的时候,有14小时的数据需要处理。既然下一个迭代有更多的数据,他要花费更多时间运行。这意味着下一个迭代会有更多的数据,等等。

为了确定什么时候运行时间,让我们做一些简单的算术。首先,让我们写下一个只有一个迭代的workflow的运行时间的等式

运行时间 = 额外开销 + {处理一小时数据的时间} * {多少小时的数据}

额外开销(Overhead)指的是花费在workflow上的任何常数项时间。例如,开始一个job需要的时间会计入额外开销。使用distributed cache来分发文件的时间会计入额外开销。你会把任何独立于数据规模的时间花费放到“额外开销”的分类中去。

“处理一小时数据的时间”指的是workflow中的动态时间。这是你忽视那些额外开销,花费在处理实际数据上的时间。如何一小时的数据会增加你半小时的运行时间上,这个值应该是0.5。如果一小时的数据会增加你一小时的运行时间,这是值就是2。

为了简洁,让我们把上面那个等式通过变量来重新写一下:

T = O + P * H

为了确定workflow的稳定的运行时间,我们需要找到workflow的运行时间在哪个点上正好等于累积了的需要处理的数据量。为了做这个,我们可以简单地插入 T=H 来求解T:

T = O + P * T
T = O / (1 - P)

这就是我之前展示的等式。你可以看到,一个workflow的稳定的运行时间是和workflow中的额外开销呈线性比例的。所以如果你可以将额外开销减少25%,那么你的workflow运行时间就会减少25%。然而,一个workflow的稳定运行时间和动态处理的速率“P”不是呈线性比例的。这背后的隐含含义就是每为集群加入一台机器带来的性能提升是在减少的。

通过这个等式,我们可以回答我在文章开始时候写下的问题了。让我们一起来过一些这些问题:

为什么在我将处理能力翻倍之后,我的workflow的速度没有翻倍?

将你的机器数翻倍,会将你的“处理一小时数据需要的时间”减少50%2。这个的效果和你的运行时间的关系是完全依赖于之前的P值的。让我们用数学来展示一下。假如说你的workflow在集群的机器数量翻倍之前的运行时间是“T1”,翻倍之后是“T2”。这给了我们两个等式:

T1 = O / (1-P)
T2 = O / (1 - P/2)

那么性能加速就会是 T2/T2,新的运行时间和旧的运行时间的比值。这给到我们

T2 / T1 = (1 - P) / (1 - P/2)
T2 / T1 = 1 - P / (2 - P)

对这个式子作图,我们可以得到如下的图,其中原始的P在x轴上,性能加速在y轴3上:

这个图说明了一切。如果你的P非常高,比如说,需要54分钟来处理一小时的数据,那么将你的集群数量翻倍会使得你新的运行时间是原来的18%,足足有82%的性能加速!这是一个非常违背直觉的结论 —— 我强烈推荐读者们仔细思考这种情况出现的背后的机制。

然后,如果你之前的P没有那么高(例如,需要6分钟的动态运行时间来处理1小时的数据),那么将集群数量翻倍对于运行时间几乎没有效果 —— 可能只有类似6%。由于运行时间被额外开销所主导,这是很合乎情理的,动态运行时间在运行时间中占得很小。

为什么10%的任务失败率会导致我的运行时间上升到原来的300%?

这个问题解释了workflow稳定性的属性。在一个大集群中,你总是会有不同的机器故障,所以任务失败率的峰值不会干掉mission critical系统的性能是非常重要的。关于这个问题的分析会和上一个问题看起来非常相似,除了我们会将动态运行时间变差而不是提高它之外。10%的任务失败率意味着我们需要多运行11%的任务来处理完我们的数据4。由于任务依赖于我们所拥有的数据量,这意味着,我们的“处理一小时数据需要的时间”会上升11%。类似于上一个问题,让我们将T1作为没有任务失败所需要的运行时间,T2作为有任务失败的运行时间

T1 = O / (1 - P)
T2 = O / (1 - 1.11*P)
T2 / T1 = (1 - P) / (1 - 1.11*P)

对此作图,我们得到:


(译著: 上图中X轴为P值,Y轴为花费时间增加的比例)

你可以看到,任务失败对于运行时间的影响在你的集群有“额外容量”减少的情况下戏剧性地增长。所以让保持你的P低是非常重要的。我们可以看到你的P越高,由于任务失败率的增加,你就更有可能进入“毁灭循环”的风险5

如果通过优化掉我的workflow的运行时间的30%而导致运行时间下降了80%?

这个问题是使得我真正找出workflow的运行时间的模型。我曾在一个workflow中有一个荒谬的瓶颈,导致了大概10小时的额外开销6,然后整个workflow的运行时间大概是30小时。在我优化了这个瓶颈(大约占据了30%的运行时间)之后,运行时间像石头一样坠落,最终稳定在6小时(减少了80%)。使用我们的模型,我们可以确定为什么这发生了:

30 = O / (1 - P)
6 = (O - 10) / (1 - P)
O = 12.5, P = 0.58

所以那10小时,占据了workflow中的80%的额外开销,这解释了整个的性能提升。

我的集群中到底需要多少机器可以满足性能和容错的需要?

这基本上是一个费效比分析的练习。我们可以看到,通过增加集群中机器数据来提高性能到回报在减少,而一旦P(“处理一小时数据需要的时间”)下降到30分钟以下(0.5),通过增加机器获得的性能提升是次线性的7。我们也同样看到将P保持得低是很重要得,不然任务失败的增加或者其他的任务使用集群,会严重影响你的运行时间。所以,你需要运行一些数据来确定对你的应用最佳的机器数量8

你应该在Twitter上follow

更新:看看本文的后续内容



1 事实上,这个等式适用于任何批量处理连续数据流的系统。
2 这里假设你的处理是完全分布式的,并且没有持有任何中心点,这对于一个基于Hadoop的workflow来说通常是真的。一个可能的例外是,你所有的tasks都通过一个中心的数据库进行通信。事实上,增加更多的机器会在额外开销(更多的机器去处理)以及数据处理速率(mapper需要将数据分发到更多的reducer中去)有少量的不利影响。对于这个分析的目的来说,我们可以忽略这些。
3 该图通过FooPlot生成。
4 比如说我们通过100个task来处理数据,现在,当你运行这些task的时候,其中有10个会失败。当你重新运行这10个的时候,9个会成功,还有1一个会失败。所以你实际运行了111个task而不是100个,这意味着task的数量增加了11%。
5 或者其他的运行在集群上的东西,比如一次性的查询或者其他的workflow。
6 这是由于Berkeley DB在ext3的文件系统上会生成很多碎片。
7 事实上,我没有展示这个,但是你可以通过模型来自己推导。我把这个作为一个练习留给读者。
8 如果你需要的话,你可以让这个模型变得更加全面。比如,这个模型没有区分新进入的数据和已经存在需要被查询的数据(并且在每个迭代中都会增加)。这个变量必然会影响到你的长期扩展需求,记住它是非常重要的。对于那些知识对于这些workflow的性能有获得一个直觉的目的来说,这不是必须的。


Yet Another Year

又是超快的一年过去了,特别是从7月份开始,都觉得没有怎么喘气,一下子就2012了,翻了一下去年的新年愿望,发现完成度依然很低啊,但是其实过去这一年收获很大,在多年觉得自己没有太大成长之后,又有了升级涨经验值的感觉,在30之前再次找到这种感觉,还算是很不错的。

去年对于今年设想中,除了给Mahout打了几个超级简单的Patch之外和飞的海南过了个周末之外,其余都没有达成,生活变化得太快。忽然又开始重新承担技术管理者的角色,于是对于自身技术研究的很多设想只好放下不少,其实到现在我也还会有点怀疑回到管理者角色而不是专心写代码对我究竟是合适还是不合适,但是被逼着同时run好几个项目和模块反而在这上面重新有了不少的成长。负面效应是,集中思考记忆的能力大大下降,以前一天看个一两百页英文技术书籍不成问题,最近看个十页精神就集中不起来了,这个需要自己好好调整一下了。

想看的技术书籍没有一本看完的,SICP没动,PRML只是少量温习了去年看过的一部分,POSA完全没看,不过现在反而觉得POSA没有必要看了。但是还是一贯漫无目的的看了一些其他的,Mahout In Action看了半本,不准备接着看完,Manning的In Action系列也没有必要预先看。DSL看了一半,有点Boring,目前看到的都是我知道的内容,但是从来没有整理过知识体系,The Joy Of Clojure看了个开头。今年所有的成长感都来自”Learning By Doing”,唯一和工作相关性比较大的书是Behind The Closed Door,让自己重新找回了点感觉。

如果说每年学一门新的编程语言的话,今年能勉强算得上的就是Pig这门DSL了,相当好用啊。明年的话,应该是尝试用点Clojure,继续多用用Ruby,少用用“新时代的汇编语言”Java。

新的一年,有一些过去的目标要放弃,我自己可不是什么天才,新的一年里,争取翻一遍PRML吧,不敢说看完了,其他的,看到哪里算哪里,The Joy of Clojure估计可以轻松看完,其余的预计也抽不出太多时间。另外,争取每两周写一篇Blog吧,除了类似新年这种事情,不写生活类了,多做点有实际价值的东西吧。

对于工作,很高兴和很多超级聪明勤奋的人一起工作,希望今年能真真正正用技术手段帮公司多挣到一点钱。希望团队里的同学们都能觉得每天来上班是高兴的一件事情,少点由于我的混乱带来的加班,多点让人兴奋的新系统,新模型,新Feature带来的效果。

过去一年比较糟糕的是,忽然开始有白发,长了10斤肉到肚子上,真的要开始锻炼了,不然蹦跶不了几年了。要去把已经过期了的护照和港澳通行证办好,无论如何带儿子去趟香港,少上网,少上微博,多读书,多走动,多运动,多思考。

去年说不再多花钱在电子产品上的,但是最终还是年前签了个iPhone,然后瞬间安逸了,明年真的没有什么可买的了,把买来的书都看看完吧。

最后,祝福某两人啊,很为你们感到高兴:-)。


运营一个系统比开发一个系统更重要

互联网公司和软件公司最大的不同在于,即使对于技术团队来说,开发工作也只是一小部分工作,如何使得整个系统运营起来,才是重头戏,这是过去一年感悟最深的一点;而对于像广告质量这样的技术团队来说,运营和开发可以说是完全不可分离的。过去一年,在这点上,走了很多弯路,犯了很多错误,有很多可以总结的地方。从Quora上看到这样一个问题,“What are the keys to operationalizing a machine learning ranking system from an organization / engineering management point of view?”

觉得唯一的一个回答就很好,翻译一下以记之,虽然做不到信达雅,但是基本意思应该能描述对。

这个问题的大概内容是这样的:


如果从组织管理/工程管理的角度来看,什么是将一个机器学习的Ranking系统运营起来的关键点?
对于那些有基于机器学习或者其他方式有Ranking系统的组织,可以保证他们运行平稳,并且随着时间的推移慢慢进步?哪些监控是重要的?如何定义目标,目标由谁来定义?如何分辨效果的提升来自于Feature工程团队还是核心算法上的提升?哪些严重依赖于Ranking的组织如何为这些来构造他们的流程?


目前唯一可见的回答,来自前Google的工程师Brandon Ballinger:


我之前在Google做语音识别和广告,这两者都以机器学习作为他们的核心。下面是我从“野外”学到的如何运营一个机器学习系统的一些重要的经验和教训

  • 将你的成功的指标定义为让用户高兴。传统的精确性的指标,比如precision, square error, ROC等等并不能捕捉到那些你真正关心的——用户对于你的模型是如何反应的。例如,如果你运营一个广告系统,你的指标应该是每个PV的收入以及点击率。完全有可能,由于辛普森悖论,你有一个error rate减少了的模型,但是他带来的收入却降低了。
  • 核心指标下降是很严重的问题。你需要把核心指标的大幅下降当成和一个服务器当机或者数据库中数据损坏一样严重的问题。Oncall的人需要尝试尽快诊断问题,并且必要时把别人拉进来一起解决问题
  • 对每次Model的Launch做A/B测试。你应当始终并行运行两个模型,给不同的用于用不同的模型,然后比较用户行为。这是唯一可以确保你知道你在做正确的事情的办法。
  • 小心丑小鸭效应。机器学习系统会在从自己的错误中学习的过程中变得更加准确。这意味着,新的模型有一个与生固来的缺陷:你的历史训练数据包含着过去模型中的错误,但不是你新训练的模型的错误。导致你的新模型一开始可能像一个丑小鸭,但是如果你用他来决策用户看到的内容,他最后会变成一个漂亮的天鹅。你可以通过将一小部分流量切给新模型,来部分抵消丑小鸭效应,然后慢慢随时间提高这个百分比。
  • 使得算法对于噪声Feature健壮。类似于L1 regularization这样的技术可以使得你的机器学习算法对Feature进行剪枝,修剪掉那些对于预测的准确性贡献很小的Feature。这可以帮助你很好地拆分你的团队:一些人专注于算法,另一些人写Feature喂给算法。那些寻找Feature的人,可以直接“把东西扔进锅里”,然后让算法找出他们究竟好还是不好。(类似的,你应该通过确保合理的收敛性来选择一个算法)
  • 你可以部分地将架构和算法团队解耦合。基本上,大部分机器学习算法都是在累计一个分布式的hash table的统计信息,然后将这些统计信息合并成一个分数。开发一个分布式的hash table是和开发一个用于累计的算法不同的任务,可以由不同的子Team完成。然后,让这些人一起工作仍然是很重要的。例如,一些算法在写入和写入可用之前延时的“最终一致”的系统中(例如Dynamo),会有所波动。所以这只是一个部分解耦合,你仍然需要团队中有连接架构和算法的“桥梁”人员。
  • 在在线系统和批处理系统之间选择的时候要小心。一个在线系统可以实时学习,对于新的用户行为,可以在发生之后的几分钟内有所反应。但是这回带来巨大的开销,一个在线系统需要2-3倍的时间区开发和维护,而且他对瞬间的变化更加敏感。举个例子,如果你突然接收到了很多垃圾信息,这些噪声会立刻被吸收进你的系统并且开始降低用户的体验。类似的,一台机器如果没有可运行的内容了,如果网络连接中断了,或者一个特定的机器变慢了(导致Feature“歪了”),模型的某个输入开始生产垃圾,等等。
  • 为所有东西打上版本。一个训练过的模型依赖于稳定的标识,如果你更改了某个标识,模型立刻就过时了。例如,如果你将用户的语言(“en-us”)作为一个feature。那么当有些人提交了一个一行的修改,用下划线替换了短横线(“en_us”)。这使得模型立刻“忘记”了所有从”en-us”中学到的,使得所有的语言看起来都是一样的。所以为所有会在你模型中生成标识的代码和数据的变更都打上版本。
  • 你需要咬碎100-1000倍于实时的数据。如果你的训练数据来自于整整一年的历史数据,然后你的学习过程是10倍于实时,那他需要一个月来测试一个新Feature。把所有的东西都写成Map-Reduce或者Storm Topology使得你可以在数据变得足够大的时候仍然可以扩展。

看了一下,里面有不少错误我们都犯过,包括过去一个Q我们觉得由于团队小应该快点冲而省略掉的东西,现在看来也还是省略不掉的,而之前做对的部分也都是来自老大们的经验,希望今年少走弯路效果好啊。


其实都是些常规

首先,打破一切常规
读完了这本书,其实多年以前随便乱翻书的时候应该已经读过,不过当时读了也是白读。

读完整本书,觉得有点儿料的还是那12个问题,非常Practical,而且仔细想了一下,如果这12点一个经理能够做好,基本上整个团队应该算是积极向上正向循环了的。

但是除此之外,整本书感觉就是平平了,一个是后面大量的所谓发挥优势,寻找才干之类的部分陷入了完全难以实践应用的怪圈,很多话颠过来倒过去,比如才干这个概念,看完全书你也很难定义出什么是才干,而这个,基本上是这本书核心的基本概念了。

我比较认同的部分是了解你的员工这一部分,了解每个人的性格禀赋理想,对于团队的长期成长和稳定是很有帮助的,但是我是认为很多时候,技能态度经验太难和才干分开,强行去寻找所谓才干可能没有太大实践意义。

才干后续部分的有些Practice倒是值得实践一下,包括花更多的时间和最好的员工在一起,包括尽量发挥优势而去避免弱点,而不是去补上所谓的缺陷。不过对于实践效果我心目中还是存疑的,一方面是在开发团队中,校招的新员工仍然是需要花大量实践培训的,而且初期欠缺的主要是经验和技能,而不是才干,不然可能就是完全浪费了才干,而在一个快速成长扩张的团队中,这个可能会占用很多时间,另外是避免弱点是否可能导致大量Senior的工程师反而不能独立工作,或者说放弃独立工作的需求?

宽带工资之类的公司层面的实践,在高科技企业总体其实实践得不错,大部分公司都有技术和管理两个Career Path,所以没什么可多说的,对于传统企业反而是可能比较有参考意义。

总体来说,看完了需要做的是:

  • 尝试一些Practice,比如花更多的时间和精力和最好的员工在一起。
  • 不断回顾对于12个问题具体做得怎么样。
  • 了解团队里的每个人。
  • 对于技术团队的管理,我倒是比较推崇另外一本书Behind Closed Doors:Secrets of Great Management,相对更加practical,而且,就像书里说得那样,大部分事情都是很小很简单的,但是需要的是持续的实践练习。


入手了个Kindle

一方面是收到K总蛊惑,一方面是决定调整下多看点书,不能每天浪费太多时间刷微博,但是天天带iPad一是沉,而是的确很费眼睛。于是小长假前未经领导批示,大出血入了Kindle 3G+官方带灯皮套,目前看来,Kindle物有所值,受K总忽悠入了3G版其实意义不大,带灯皮套很好,但是价格太坑爹了。

3月份过完年的时候给老妈买了个百看,这次本来也是在各类电子书之间犹豫的,买了Kindle主要还是看重有些书可以直接在Amazon买Kindle版,排版比自己用PDF转的要好多了。到手之后,发现做工上Kindle还是比百看强出一条街的,翻页响应也快不少,不过就是保修麻烦,而上次那个百看买了两个月都没怎么用过就花屏了,寄回京东重新换了个新的。所以这回干脆狠狠心入了个皮套,想想3G版都买了,于是干脆入了个带灯的皮套,于是最后花出去的钱基本可以买两个广告版的了,还是比较烧包的。

用了两天,总结如下:

  • 从看书来说,E-Ink秒杀一切,除了随手写写画画和快速翻页比不上纸质书,其余都远远超出,而且如果是用来看非技术类书籍,因为基本不需要记录,可以认为是完美,甚至可以说超过了纸质书
  • Kindle最大的优势应该是Amazon背后强大的内容,这个其实和iPad是一样的,我先是下了个Kindle版的Domain Specific Languages的sample,看完了Chapter1.1于是掏出信用卡买了全本电子版。
  • 3G对美国人民可能很有用,但是对中国人民意思不大,会检查你的ip所在的国度,要求传真验证地址身份,看看到时候麻烦哪位在美国的同学把Kindle挂到他名下去
  • 皮套的保护很不错,可是太厚重了,加了皮套单手持着就有些中了。灯很有意义,特别是晚上坐公车回家的时候,供电设计也很有意思,只是不能均匀照射到整个屏幕
  • 6寸的Kindle,用来看技术书,如果是Kindle版的或者正版制作好的mobi版可以接受,但是Kindle DXG应该会更加完美
  • 键盘加bookmark和note还是有一定意义的,内置字典非常有用,没有必要刷多看,原生系统用来看书足够了
  • 原生的PDF阅读功能基本没用,书还是要转成Mobi,因为PDF的不能重排也不能调字体,所以等于没用,专门制作的6寸的PDF太罕见了,而且如果是专门制作的,完全可以搞Mobi么

Anyway,结论是,重度阅读者必备工具啊,让随时随地的阅读体验大大提升。

回过头来说,书籍电子化已经发展了很多年了,然而作为一个中国人民,想舒舒服服看电子书仍然只有糟糕的两个选择,盗版,或者装作一个美国人民。就像我前面说得,Kindle对我来说,最有吸引力的并不是3G上网或者硬件设备,而是在良好的阅读体验之上,Amazon拥有的无数Well-Formatted的书,这样我就不再需要买纸质书占地方了,而且所有的书,我都可以在看完sample之后决定要不要买,从这个角度来说,Kindle 3G可以提供的可以说是最佳的购书体验了。不需要你没有看过书就决定买不买(目前国内网上买书最大的缺点是很多书不知道值不值得买来看),也不许要跑到书店里去买(我已经多年没有进过书店了,但是这几年),甚至都不需要等快递送上门了(有时候想看书买了之后等快递要一个礼拜)。

可惜,这些优势都是只有美国人民有,中国人民只能 1. 装作美国人掏美刀跑到Amazon上买还要受歧视不让你买 2. 盗版,而且那么多年,这些国内的出版商和零售商真是完全不思进取,严肃书籍,除了China-Pub搞了些没人看的技术书籍电子版之外,就没有人有动作的。我一直认为,最蠢的一种想法就是惧怕盗版,要知道,这个阵地他们不占领,就会被盗版占领,现在互联网上已经有大量的自制的盗版版本了,质量虽然比不上Amazon Kindle的那种,有些错字,但是完全可以看了,不出电子版,就只能坐等大家去看盗版。如果真能够做到像Amazon在北美那样,可以试看,购买,同步,记笔记,同步笔记,然后绑定好设备来给盗版增加麻烦,我相信虽然不可能是一个iPad这样的市场,也会完全是一个有得做的市场,事实上,国内目前的iOS的App也有不少的正版软件消费量了。

当然,其实大家都知道,国内的出版商和在线零售商是没有足够的技术支撑来干这事儿的,唯一有点指望的是卓越能够跨过外资这道门槛把Amazon在美国的服务复制到中国来,或者,用脚投票投奔U.S.A.去。如果国内的电子书渠道能够像Amazon在美国这样,我想我就会考虑再入一台Kindle DXG的。


支持Ruby1.9的MRToolkit

虽然最近的工作整天用Java写各类数据处理代码,但是去年大半年用惯了Ruby的我每每要写个测试或者临时计算的MapReduce都觉得真是太麻烦了,于是又念叨起Ruby的好来了。

先看了看利用Hadoop Streaming和Ruby来写MapReduce,发现还是有些麻烦,一是mapper和reducer要分开两个文件,二是每个任务都要重复写从stdin读取数据解析,以及输出的代码,一点不符合DRY原则,于是就找到了mrtoolkit,然后一连串杯具开始发生了。

麻烦LJ同学先给所有的机器装了Ruby1.9,然后一跑,杯具地发现没跑起来,然后发现部分代码不兼容1.9……好吧,反正没多少源代码,改之,再跑,发现虽然每台机器都下载了mrtoolkit而且都设好了RUBYLIB但还是没能成功require mrtoolkit;于是,上github抄了个别人更改的mrtoolkit版本的gemspec和Rakefile,然后打包成gem,然后安装,于是MapReduce任务在各个node上跑起来了,但是,有一部分失败了,杯具地发现Ruby1.9开始对于字符串encoding有了很多限制,使用split通过正则分割字符串的时候居然还检查整个字符串的encoding的合法性,而我们要处理的日志里会存在GBK和UTF-8混在一行编码的可能性……试了好多种方法都不行,只好再跑到邮件组上去问,得高人指点先把字符串转成BINARY的encoding进行分割,然后再转回来,终于……能用了。

所以现在就有了这个支持Ruby1.9的mrtoolkit的版本啦,首个release包含以下变更:

  • 支持Ruby1.9
  • 将hadoop streaming中deprecated的-jobconf参数改成了-D
  • 单行的文本编码可以是混合编码的不合法的Ruby1.9的字符串
  • 可以打包成gem安装(抄袭自jashmenn的版本)

还准备做个小改动是默认output目录存在时输出警告,并且不提交任务不删除输出目录,直接删除现有的输出目录这种方法太容易搞出事情来了。


建议的程序员学习LDA算法的步骤

这一阵为了工作上的关系,花了点时间学习了一下LDA算法,说实话,对于我这个学CS而非学数学的人来说,除了集体智慧编程这本书之外基本没怎么看过机器学习的人来说,一开始还真是摸不太到门道,前前后后快要四个月了,算是基本了解了这个算法的实现,记录一下,也供后来人快速入门做个参考。

一开始直接就下了Blei的原始的那篇论文来看,但是看了个开头就被Dirichlet分布和几个数学公式打倒,然后因为专心在写项目中的具体的代码,也就先放下了。但是因为发现完全忘记了本科学的概率和统计的内容,只好回头去看大学时候概率论的教材,发现早不知道借给谁了,于是上网买了本,花了几天时间大致回顾了一遍概率论的知识,什么贝叶斯全概率公式,正态分布,二项分布之类的。
后来晚上没事儿的时候,去水木的AI版转了转,了解到了Machine Learning的圣经PRML,考虑到反正也是要长期学习了,搞了电子版,同时上淘宝买了个打印胶装的版本。春节里每天晚上看一点儿,扫了一下前两章,再次回顾了一下基本数学知识,然后了解了下贝叶斯学派那种采用共轭先验来建模的方式。于是再次尝试回头去看Blei的那篇论文,发现还是看不太懂,于是又放下了。然后某天Tony让我准备准备给复旦的同学们share一下我们项目中LDA的使用,为了不露怯,又去翻论文,正好看到Science上这篇Topic Models Vs. Unstructured Data的科普性质的文章,翻了一遍之后,再去PRML里看了一遍Graphic Models那一张,觉得对于LDA想解决的问题和方法了解了更清楚了。之后从search engine里搜到这篇文章,然后根据推荐读了一部分的Gibbs Sampling for the Uninitiated。之后忘了怎么又搜到了Mark Steyvers和Tom Griffiths合著的Probabilistic Topic Models,在某个周末往返北京的飞机上读完了,觉得基本上模型训练过程也明白了。再之后就是读了一下这个最简版的LDA Gibbs Sampling的实现,再回过头读了一下PLDA的源码,基本上算是对LDA有了个相对清楚的了解。

这样前前后后,也过去了三个月,其实不少时间都是浪费掉的,比如Blei的论文在没有任何相关知识的情况下一开始读了好几次,都没读完而且得到到信息也很有限,如果重新总结一下,我觉得对于我们这些门外汉程序员来说,想了解LDA大概需要这些知识:

  • 有基本的概率论的知识,这个拿个大学的课本大概翻一下就好了
  • PRML的前两章和Graphic Model那部分需要浏览一下,了解一下所谓的贝叶斯学派的方法论,然后理解共轭先验的概念,以及Graphic Model的图形表达的意思。
  • 了解一下Gibbs Sampling的概念
  • 直接读Steyvers的Probabilistic Topic Models,没必要一定去读Blei的论文,开创性的论文不一定好读,最典型的例子就是Paxos了,30多页里多少都是希腊人名,对于英文不够精通,学术训练比较少的工程师来说,其实很痛苦,意义也不大。
  • 对照着Probabilistic Topic Models直接看LdaGibbsSampling.java的源码

基本上这样一圈下来,基本概念和算法实现都应该搞定了,当然,数学证明其实没那么容易就搞定,但是对于工程师来说,先把这些搞定就能干活了,这个步骤并不适合各位读博士发论文的同学们,但是这样先看看也比较容易对于这些数学问题的兴趣,不然,成天对这符号和数学公式,没有整块业余时间的我是觉得还是容易退缩放弃的。

发现作为工程师来说,还是看代码比较有感觉,看实际应用的实例比较有感觉,看来不能把大部分时间花在PRML上,还是要多对照着代码看。


Go Back to the Fundamental

这周LJ发现系统里有大量的缓存没有清掉,一开始误以为是我的定时提交的Job中有什么问题,虽然最终发现是因为系统对于验证阶段不能通过的Job就会缓存Job文件供日后分析,但是在怀疑自己提交的Job有问题的时候,花了两天时间清理掉了以前没有解决的Bug,并且进一步发现了某些Bug的深层原因。这事儿又是给自己一个教训,一是凡是出错必有原因。二是所有新功能都应当在显然是Bug的东西修复了之后完成。其实这样的错误不是第一次犯了,而且从道理上也清楚的知道该怎么做,但是时不时总会觉得自己已经有足够的经验去把握各种优先级了,于是时不时就会再犯一次,希望这是最后一次了。大部分事情要做好其实很简单,按照自然规律,一步一步仔仔细细做完,Over,可惜总是急躁地想抄近道,最后在事后付出代价。好在的确工作年限多了点,现在犯的错误往往不是致命的,最多也就是多浪费了那么一点时间罢了。

今天又和好久未见的Mars同学聊了一阵,现在我们算是一个行业里了,聊到目前飞速发展的互联网和电子商务,一边感慨的确入对了行,一边也都觉得行业里大部分的人还都是过于浮躁了,机会虽然看起来很多,但是大家都急冲冲地做的结果就是门槛看似很低,但是大部分都会死。然而很多死者,无论是做技术还是做市场做商务的,其实都没有真正做到把自己的事情做好,也许真是要退潮了,才能看出谁是裸泳者。

其实这个和写程序是一样的,问题暴露出来之前,各种抄近道导致的Tech Debt都不会被意识到的,所以还是告诫自己,有耐心地,一点一滴的把事情做好。

看了看春节里写的今年看三本书的计划,当时我还觉得时间还蛮宽裕的,但是仔细算算,其实也不怎么够用,如果每天看个一两节,其实看完这三本书一年都不够,不管了,每天1-3节吧,多了也坚持不下来的。


不对自我设限与来自未来的挑战

话说我是一贯认为程序员是个很有前途的职业,因为工作的这几年来,最大的感触就是好的程序员太少,好的程序员的供给,其实是远远小于市场的需求的。这个原因有两方面,一方面是,贵国发展太快,聪明的孩子们现在的选择太多,当PM的,当Dev Manager的,甚或是转行去读MBA的,考公务员的,搞金融的,总之是聪明人的挣钱过舒服日子的实在不少,于是,程序员这个很有前途的职业就被大家放弃了;另一方面,互联网行业在贵国发展太快,现在需要好的程序员的公司实在太多。这样一两面夹击,您要真是能做个优秀的开发人员,过过中产生活应当是绰绰有余(当然,您要在北京二环买房,没有个叫李刚的爸爸可能买不了)。而且,您要真是个优秀的程序员,也是可以干到60岁的,常见的所谓30岁怎么办,其实是个巨大的误区,这个问题,因为不是本文的主旨,所以就不展开讨论了,下次专门写个文章说一下为啥这行业可以干到60岁。

然而尽管我如此认为,我最近也时常想,也许20年后我也不一定每天写程序了,虽然每天写程序的概率仍然很大。之所以这么想,其中有一部分是因为这个链接。想想几十年前,汽车业也是最NB,最伟大的行业啊,虽然现在也算不上夕阳行业了,但是远不如那时候那么激动人心了。想想福特的蓝血十杰,要搁现在应该都去华尔街或者干互联网了吧。所以虽然现在的互联网仍然是风起云涌,是各位好人们挥洒大好青春的领地,但是在等20年,可能最刺激的时代就会过去了吧。而我之所以现在仍然自称喜欢写程序,无非是三方面的原因,一是求知的乐趣,二是看得到奔头的物质回报,三是觉得自己好歹在创造点有用的东西的成就感。而每当看到这样的文章的我,就容易头脑发热,觉得自己死活应该去读个博士。

所以我想,虽然我接下来四五年一定是在做程序员这个很有前途的行业,但是几年以后如果能像Elon Musk或者John Carmack一样参与到发射火箭的活动中,我会毫不犹豫跑去吧,所以为了这个,我也应该做个学好数学的程序员吧,对于擅长逻辑思维和计算的我,写程序和数学算是我未来有机会跨行业干活的重要工具吧。

说到这里估计会被人当作少不经事太爱幻想,不过这几年我越来越发现人不能对自我设限,自我设限通常结果不是让你脚踏实地而是容易让你原地踏步。本来我想我大学没好好念书,也就不想啥再去读个PhD了,但是看了Paul McKenney老人家的简历,我觉其实准备准备也可以考虑三四十去读个PhD么?以前总觉得没指望名片上从Mr.改成Dr.的限制其实都来自自己么?其实,工作了这几年,越来越发现,其实身边的大牛们,并没有比我多个脑袋,或者一定每天只需要睡4个小时,无非是天赋、机遇、眼界,加上日供一卒的努力罢了,大部分身边的大牛们,和你我的差别不在天赋上,不在机遇上,而往往是在眼界和每日持续的努力上。而自我设限,一是愣把眼界降低一层,非觉得别人能拿一等奖能读博,自己不能总只想着卖烧饼;二是往往主动放弃了每天向前一点点的努力,因为觉得读不了博了干脆就不学点儿难的数学GRE或者Lisp了。最后是啥也没干成,但这种自我预言的实现是十足地犯傻呢。

未来还很长呢,想想十多年前上大学的时候,我还没手机呢,现在手机3G上网都比我家上网快了,又有谁会知道15年后我会去干什么,虽然多半我仍然在写着我那很有前途的程序,兴许外星人真来了我去当翻译了呢。虽然,图灵奖我估摸着的确应该是拿不了了,但咱们怎么也这辈子读个博士,发两篇有点儿意义的论文先吧。


新年愿望

去年基本没写Blog,回想一下,去年想干的几件事,基本都没善终,希望今年有所改观

总结下去年的生产力

  • I公司的产品,技术的推动,基本上算是满盘皆输,心理感觉都快和程序员阿士顿的故事差不多了,花了很多时间精力,但是就是没有实际的商业成果。最后11月份放弃换工作了。
  • 手机开发,本来想自己写个iPhone App的,最后也没有抽出时间来写,基本上Objective-C的程序架构都清楚了,debug也行,但是实际除了Example没有写过什么。
  • Ruby和Rails,倒是因为一个项目重新拾起,但是换了工作之后又放下了,不过现在的脚本都用Ruby写了,算勉强保持点功力吧。
  • Lisp,做了点SICP上的题,本来雄心壮志准备去年做完的,但是换了工作,又玩新东西去了,目前停留在第二章,今年怎么也把这本书上的题做完吧
  • 儿子的某大事还算成功,算是了了一半心事。春天的时候去乌镇过了个周末,我非常喜欢那里,准备今年至少再去一次
  • 最后,托HL总的福,换了个新工作,目前很满意,开始做些有追求的大系统,感谢HL总和NH姐姐。当然,也感谢I公司的B总,很愧疚自己还是才具不够,折腾了一年半没能干成啥事儿。

今年的目标也蛮简单,技术上和实际工作基本上完全一致,就是分布式和机器学习了,硬指标基本上是三本书,去年没看完的SICP做完所有得题,分布式看完POSA第四卷,以及机器学习看完PRML,希望做出的系统真的能够对中国互联网有点影响,希望能为Hadoop/HBase/Zookeeper/Mahout/S4这些开源项目贡献点代码。生活上么,去次海南,再去次乌镇,有机会的话,再出趟国,以后能像我毕业前三年那样每年都出去见识见识。对自己的限制么,今年不烧包买大件了,iPad、手机、笔记本电脑都不会更新换代,得开始稍微省点儿钱了。本来还想学门乐器,算算多半也不会有时间,今年就不考虑了,先重新把数学学好吧。还有就是真得锻炼身体了,游泳圈开始初现端倪了……