沐鳴:_如何閱讀別人的代碼?

挺多人問過我“如何閱讀已有代碼”這個問題,希望我能有一個好的方法。有些人希望通過閱讀“優質項目”(比如 Linux 內核)得到啟發,改進自己的代碼質量。對於這個問題,我一般都不好回答,因為我很少從閱讀別人的代碼得到提升。每一次閱讀別人的代碼,對我來說都是一種折磨,而且每一次都不是別人的代碼提升了我,而是我提升了別人的代碼。

比起閱讀代碼,我更喜歡看別人的文章或者書。我喜歡他們跟我面對面的交流,用簡單的自然語言或者畫圖解釋他們的思想。有了思想,我自然知道如何把它變成代碼,而且是優雅的代碼。每一次參加學術會議,我都發現自己幾乎無法理解會議上的 talk 或者 paper。我會在 talk 結束之後的喝茶時間走到演講者面前,對他說:“你的 talk 很有意思,你能在三句話之內總結一下你說了什麼嗎?” 這樣交流之後,我忽然就懂了。

如果有同事請我幫他改進代碼,我不會拿起代碼埋頭看,因為我知道看代碼往往是沒用的。我會讓他們先在白板上給我解釋那些代碼是什麼意思。我的同事們都發現,把我講明白是很困難的。因為我的要求非常高,只要有一點不明白,我就會讓他們重新講。還得畫圖,我會讓他們反覆改進畫出來的圖,直到我能一眼看明白為止。如果圖形是 3D 的,我會讓他們給我壓縮成 2D 的,理解了之後再“推廣”到 3D。我無法理解複雜的,高維度的概念,他們必須把它給我變得很簡單。

所以跟我講代碼總是需要費很多時間,但這是值得的,因為我明白了之後,往往能挖出其他人都難以看清楚的要點。給我講解事情,也能提升他們自己的思維和語言能力,幫助他們簡化思想,甚至在忽然間發現改進他們自己代碼的方法。很多時候我根本沒看代碼,通過給我講解,後來他們自己就把代碼給簡化了。節省了我的腦力和視力,他們也得到了提高。

我最近一次看別人的代碼是在 Intel,我們改了 PyTorch 的代碼。那不是一次愉悅的經歷,因為雖然很多人覺得 PyTorch “好用”,它內部的代碼卻是非常晦澀,難以理解的。PyTorch 不是 Intel 自己的東西,所以沒有人可以給我講。修改 PyTorch 代碼,增加新功能的時候,我發現很難從代碼本身看明白應該改哪裡。後來我發現,原因在於 PyTorch 的編譯構架里自動生成了很多代碼,導致你無法理解那些代碼是怎麼來的。

比如他們有好幾個自己設計的文件格式,裏面有一些特殊的文本,決定了如何在編譯時生成代碼。你得理解這些文件裏面的內容在說什麼,而那不是任何已知的語言。這些文本文件被一些 Python 腳本讀進去,吐出來一些奇怪的 C++,CUDA,或者 Python 代碼。這其實是一種 DSL。我已經在之前的文章中解釋過 DSL 帶來的問題。所以要往 PyTorch 裏面加功能,你就得理解這些腳本是如何處理這些文本文件,生成代碼。而這些腳本寫得也比較混亂和草率,所以就是頭痛 2 ,頭痛的平方。

最後我發現,根本沒有辦法完全依靠這些代碼本身來理解它。那麼怎麼解決這個問題呢?幸好,網絡上有 PyTorch 的內部工程師寫了篇 blog ,解釋 PyTorch 如何組織代碼。Blog 的作者 E. Z. Yang 我見過一面,是在一次 PL 學術會議上。他當時在 MIT 讀書,貌似一個挺聰明的小伙子。不過看了這 blog 也只能初步知道它做了什麼,應該碰大概哪些文件,而這些每天都可能變化。

這篇 blog 還提到,某幾個目錄裏面是歷史遺留代碼,如果你不知道那是什麼,那麼請不要碰!看看那幾個目錄,裏面都是一些利用 C 語言的宏處理生成代碼的模板,而它使用 C 語言宏的方式還跟普通的用法不一樣。在我看來,所謂“宏”(macro)和 metaprogramming 本身就是一個巨大的誤區,而 PyTorch 對宏的用法還如此奇怪,自作聰明。

你以為看了這篇 blog 就能理解 PyTorch 代碼了嗎?不,仍然是每天各種碰壁。大量的經驗都來自折騰,碰壁,在黑暗中摸索。多個人同時在進行這些事情,然後分享自己的經驗。討論會內容經常是:“我發現要做這個,得在這個文件里加這個,然後在那個文件里加那個…… 然後好像就行了。” 下次開會又有人說:“我發現不是像你說的那樣,還得改這裏和這裏,而那裡不是關鍵……” 許多的知其然不知其所以然,盲人摸象,因為“所以然”已經被 PyTorch 原來的作者們掩蓋在一堆堆混亂的 DSL 下面了。

所以我從 PyTorch 的代碼裏面學到了什麼呢?什麼都沒有。我只看到各種軟件開發的誤區在反覆上演。如果他們在早期得到我的建議,根本不可能把代碼組織成這種樣子,不可能有這麼多的宏處理,代碼生成,DSL。PyTorch 之類的深度學習框架,本質上是某種簡單編程語言的解釋器,只不過這些語言寫出來的函數可以求導而已。而寫解釋器是我最在行的事情。

那麼我是怎麼成為現在這個樣子的呢?肯定有某種方法,對吧。我的方法很簡單,寫最短最精巧的代碼,從最薄最精悍的書或者課程裏面學,從真正的大師那裡學,而不是大型開源項目。

造就我今天的編程能力和洞察力的,不是幾百萬行的大型項目,而是小到幾行,幾十行之短的練習。不要小看了這些短小的代碼,它們就是編程最精髓的東西。反反覆復琢磨這些短小的代碼,不斷改進和提煉裏面的結構,磨礪自己的思維。逐漸的,你的認識水平就超越了所有這些幾百萬行,讓人頭痛的項目。

很多人都不知道,有一天我用不到一百行 Scheme 代碼就寫出了一個“深度學習框架”,它其實是一個小的編程語言。雖然沒有性能可言,沒有任何 GPU 加速,功能也不完善,但它抓住了 PyTorch 等大型框架的本質——用這個語言寫出來的函數能自動求導。這種洞察力才是最關鍵的東西,只要抓住了關鍵,細節都可以在需要的時候琢磨出來。幾十行代碼反覆琢磨,往往能幫助你看透上百萬行的項目里隱藏的秘密。

所以我如何閱讀別人的代碼呢?Don’t。除非我真的要使用那個項目的代碼,我才會去折騰它。

原文 http://www.yinwang.org/blog-cn/2020/02/05/how-to-read-code

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/7434