算法是計算機科學領域最重要的基石之一,但卻受到了國內一些程序員的冷落。許多學生看到一些公司在招聘時要求的編程語言五花八門就產生了一種誤解,認爲學計算機就是學各類編程語言,或者認爲,學習最新的語言、技術、標準就是最好的鋪路方法。其實你們都被這些公司誤導了。編程語言雖然該學,可是學習計算機算法和理論更重要,由於計算機算法和理論更重要,由於計算機語言和開發平臺突飛猛進,但萬變不離其宗的是那些算法和理論,例如數據結構、算法、編譯原理、計算機體系結構、關係型數據庫原理等等。在「開復學生網」上,有位同窗生動地把這些基礎課程比擬爲「內功」,把新的語言、技術、標準比擬爲「外功」。成天趕時髦的人最後只懂得招式,沒有功力,是不可能成爲高手的。
算法與我
當我在1980年轉入計算機科學系時,尚未多少人的專業方向是計算機科學。有許多其餘系的人嘲笑咱們說:「知道爲何只有大家系要加一個‘科學’,而沒有‘物理科學系’或‘化學科學系’嗎?由於人家是真的科學,不須要多此一舉,而大家本身心虛,生怕不‘科學’,才這樣此地無銀三百兩。」其實,這點他們完全弄錯了。真正學懂計算機的人(不僅是「編程匠」)都對數學有至關的造詣,既能用科學家的嚴謹思惟來求證,也能用工程師的務實手段來解決問題——而這種思惟和手段的最佳演繹就是「算法」。
記得我讀博時寫的Othello對弈軟件得到了世界冠軍。當時,得第二名的人認爲我是靠僥倖纔打贏他,不服氣地問個人程序平均每秒能搜索多少步棋,當他發現個人軟件在搜索效率上比他快60多倍時,才完全服輸。爲何在一樣的機器上,我能夠多作60倍的工做呢?這是由於我用了一個最新的算法,可以把一個指數函數轉換成四個近似的表,只要用常數時間就可獲得近似的答案。在這個例子中,是否用對算法纔是可否贏得世界冠軍的關鍵。
還記得1988年貝爾實驗室副總裁親自來訪問個人學校,目的就是爲了想了解爲何他們的語音識別系統比我開發的慢幾十倍,並且,在擴大至大詞彙系統後,速度差別更有幾百倍之多。他們雖然買了幾臺超級計算機,勉強讓系統跑了起來,但這麼貴的計算資源讓他們的產品部門很反感,由於「昂貴」的技術是沒有應用前景的。在與他們探討的過程當中,我驚訝地發現一個O(n*m)的動態規劃(dynamic programming)竟然被他們作成了O(n*n*m)。更驚訝的是,他們還爲此發表了很多文章,甚至爲本身的算法起了一個很特別的名字,並將算法提名到一個科學會議裏,但願能獲得大獎。當時,貝爾實驗室的研究員固然絕頂聰明,但他們全都是學數學、物理或電機出身,從未學過計算機科學或算法,才犯了這麼基本的錯誤。我想那些人之後不再會嘲笑學計算機科學的人了吧!
網絡時代的算法
有人也許會說:「今天計算機這麼快,算法還重要嗎?」其實永遠不會有太快的計算機,由於咱們總會想出新的應用。雖然在摩爾定律的做用下,計算機的計算能力每一年都在飛快增加,價格也在不斷降低。可咱們不要忘記,須要處理的信息量更是呈指數級的增加。如今每人天天都會創造出大量數據(照片,視頻,語音,文本等等)。日益先進的紀錄和存儲手段使咱們每一個人的信息量都在爆炸式的增加。互聯網的信息流量和日誌容量也在飛快增加。在科學研究方面,隨着研究手段的進步,數據量更是達到了史無前例的程度。不管是三維圖形、海量數據處理、機器學習、語音識別,都須要極大的計算量。在網絡時代,愈來愈多的挑戰須要靠卓越的算法來解決。
再舉另外一個網絡時代的例子。在互聯網和手機搜索,若是要找附近的咖啡店,那麼搜索引擎該怎麼處理這個請求呢?最簡單的辦法就是把整個城市的咖啡館都找出來,而後計算出它們的所在位置與你之間的距離,再進行排序,而後返回最近的結果。但該如何計算距離呢?圖論裏有很多算法能夠解決這個問題。
這麼作也許是最直觀的,但絕對不是最迅速的。若是一個城市只有爲數很少的咖啡館,那麼這麼作應該沒什麼問題,反正計算量不大。但若是一個城市裏有不少咖啡館,又有不少用戶都須要相似的搜索,那麼服務器所承受的壓力就大多了。在這種狀況下,咱們該怎樣優化算法呢?
首先,咱們能夠把整個城市的咖啡館作一次「預處理」。好比,把一個城市分紅若干個「格子(grid)」,而後根據用戶所在的位置把他放到某一個格子裏,只對格子裏的咖啡館進行距離排序。
問題又來了,若是格子大小同樣,那麼絕大多數結果均可能出如今市中心的一個格子裏,而郊區的格子裏只有極少的結果。在這種狀況下,咱們應該把市中心多分出幾個格子。更進一步,格子應該是一個「樹結構」,最頂層是一個大格——整個城市,而後逐層降低,格子愈來愈小,這樣有利於用戶進行精確搜索——若是在最底層的格子裏搜索結果很少,用戶能夠逐級上升,放大搜索範圍。
上述算法對咖啡館的例子很實用,可是它具備通用性嗎?答案是否認的。把咖啡館抽象一下,它是一個「點」,若是要搜索一個「面」該怎麼辦呢?好比,用戶想去一個水庫玩,而一個水庫有好幾個入口,那麼哪個離用戶最近呢?這個時候,上述「樹結構」就要改爲「r-tree」,由於樹中間的每個節點都是一個範圍,一個有邊界的範圍(參考:http://www.cs.umd.edu/~hjs/rtrees/index.html)。
經過這個小例子,咱們看到,應用程序的要求變幻無窮,不少時候須要把一個複雜的問題分解成若干簡單的小問題,而後再選用合適的算法和數據結構。
並行算法:Google的核心優點
上面的例子在Google裏就要算是小case了!天天Google的網站要處理十億個以上的搜索,GMail要儲存幾千萬用戶的2G郵箱,Google Earth要讓數十萬用戶同時在整個地球上遨遊,並將合適的圖片通過互聯網提交給每一個用戶。若是沒有好的算法,這些應用都沒法成爲現實。
在這些的應用中,哪怕是最基本的問題都會給傳統的計算帶來很大的挑戰。例如,天天都有十億以上的用戶訪問Google的網站,使用Google的服務,也產生不少不少的日誌(Log)。由於Log每份每秒都在飛速增長,咱們必須有聰明的辦法來進行處理。我曾經在面試中問過關於如何對Log進行一些分析處理的問題,有不少面試者的回答雖然在邏輯上正確,可是實際應用中是幾乎不可行的。按照它們的算法,即使用上幾萬臺機器,咱們的處理速度都根不上數據產生的速度。
那麼Google是如何解決這些問題的?
首先,在網絡時代,就算有最好的算法,也要能在並行計算的環境下執行。在Google的數據中心,咱們使用的是超大的並行計算機。但傳統的並行算法運行時,效率會在增長機器數量後迅速下降,也就是說,十臺機器若是有五倍的效果,增長到一千臺時也許就只有幾十倍的效果。這種事半功倍的代價是沒有哪家公司能夠負擔得起的。並且,在許多並行算法中,只要一個結點犯錯誤,全部計算都會前功盡棄。
那麼Google是如何開發出既有效率又能容錯的並行計算的呢?
Google最資深的計算機科學家Jeff Dean認識到,Google所需的絕大部分數據處理均可以歸結爲一個簡單的並行算法:Map and Reduce(http://labs.google.com/papers/mapreduce.html)。這個算法可以在不少種計算中達到至關高的效率,並且是可擴展的(也就是說,一千臺機器就算不能達到一千倍的效果,至少也能夠達到幾百倍的效果)。Map and Reduce的另一大特點是它能夠利用大批廉價的機器組成功能強大的server farm。最後,它的容錯性能異常出色,就算一個server farm宕掉一半,整個fram依然可以運行。正是由於這個天才的認識,纔有了Map and Reduce算法。藉助該算法,Google幾乎能無限地增長計算量,與突飛猛進的互聯網應用一同成長。
算法並不侷限於計算機和網絡
舉一個計算機領域外的例子:在高能物理研究方面,不少實驗每秒鐘都能幾個TB的數據量。但由於處理能力和存儲能力的不足,科學家不得不把絕大部分未經處理的數據丟棄掉。可你們要知道,新元素的信息頗有可能就藏在咱們來不及處理的數據裏面。一樣的,在其餘任何領域裏,算法能夠改變人類的生活。例如人類基因的研究,就可能由於算法而發明新的醫療方式。在國家安全領域,有效的算法可能避免下一個911的發生。在氣象方面,算法能夠更好地預測將來天災的發生,以拯救生命。
因此,若是你把計算機的發展放到應用和數據飛速增加的大環境下,你必定會發現;算法的重要性不是在日益減少,而是在日益增強。html