# 克里斯·拉特納：計算與程式語言的未來

> 從 LLVM、Swift 到 MLIR，聊編譯器設計、程式語言演進，以及硬體與軟體協同的未來。

- 原標題：#131 – Chris Lattner: The Future of Computing and Programming Languages
- 期數：第 131 期
- 釋出日期：2020-10-18
- 嘉賓 / 主題：克里斯·拉特納
- 網頁版：https://lex.qiaomu.ai/tw/ep/chris-lattner-2/
- 官方頁面：https://lexfridman.com/chris-lattner-2/
- 精讀字數：約 7613 字（閱讀約 17 分鐘）

> 本文為 lex.qiaomu.ai 基於原始訪談的 AI 改寫中文精讀，非官方翻譯；引用請註明出處並連結網頁版。

Chris Lattner 在 2000 年讀大學時開始寫 LLVM。這個專案後來變成了蘋果、Google、以及幾乎整個現代編譯器世界腳下的地基。二十年後，他親手搭起來的這套基礎設施，在他眼裡已經變成了需要被打破的物件。

他給出的理由很直接：LLVM 社群裡有一批人已經在這個專案上工作了十年。十年是很長的時間。長到你開始看不見手裡這件東西的毛病。他覺得這個社群正在走向僵化，需要新的專案進來攪局。他自己造的那個新東西叫 MLIR，現在已經掛在 LLVM 的傘下，但老一代 LLVM 開發者對它並不熟悉，於是"新的東西不可信"這種文化反應就出現了。

一個造了輪子的人，回頭說輪子該換了。這期播客裡他聊的東西遠不止編譯器：程式語言該怎麼設計、指令集為什麼要開放、摩爾定律到底死沒死、併發模型該怎麼寫進語言、GPT-3 會不會改寫程式設計、疫情之後矽谷會變成什麼樣。下面挑幾條最有資訊量的線索展開。

## 三個老闆，三種帶人的方式

訪談開場問的是 Steve Jobs、Elon Musk、Jeff Dean 各有什麼過人之處。Lattner 跟 Elon 共事的時間比跟 Jobs 長得多，所以他做了個分組對比。

他的判斷是：Jobs 更關注人的因素，Musk 更關注技術本身。

> "Steve 想造的是讓人喜歡、影響人生活的東西，他會往前面看一點，去看人們想要什麼。Elon 更關注指數級增長的規律，去預測技術會怎麼發展，而且他花大量時間和工程師泡在一起。"（Chris Lattner）

關於 Jobs 怎麼讓設計師跟工程師對話還贏得尊重，Lattner 的觀察是，Jobs 推人推得很狠，但一旦對方給出了讓他信服的解釋，他就會放手。他對工程本身是尊重的，同時他又知道什麼時候該繼續壓。讀人讀得準，你就知道對方是不是留了餘力，還能不能再榨出一點東西。這是一種很難教的能力。

Jeff Dean 被歸到完全不同的類別。Lattner 說他是個非常好的人，是典型的 Google 文化，希望身邊的人都開心，同時又極其聰明，能把人聚起來。**Jeff Dean 到今天還在寫程式碼。**他透過技術本身、透過自己動手去領導，然後把別人拉進來、激發他們。Lattner 說他甚至不覺得 Jeff 會想當 CEO 那種角色。

這三個人放在一起看，領導力沒有統一答案。要看你面對的是什麼時間、什麼地點、什麼問題。

## 不知道答案，不代表你沒資格帶隊

Lattner 說他隨著經驗增長，越來越舒服的一件事是"接受自己不知道"。

> "領導力很大一部分跟'你有正確答案'無關，跟'你能拿到正確答案'有關。"（Chris Lattner）

他講了一個具體的操作：在團隊裡營造一種環境，別搞自上而下的"我讓你做什麼你就做什麼"，鼓勵每個人都參與解決方案，並且提供一個安全的空間，讓下屬在你做錯的時候敢開口告訴你。

他自己在船業公司待過一段時間，對船怎麼設計幾乎一無所知。結果發現只要肯問大量看起來很蠢的問題，變聰明的速度會非常快。前提是周圍有一群願意教、也願意自己學的人。

這條經驗貫穿了他整期播客。後來談到疫情、談到遠端工作、談到怎麼學習新語言，他反覆回到同一個點：**把自己放進一個周圍人都比你懂的環境裡，然後問蠢問題。**聰明人通常喜歡教別人，你只要準備好聽，準備好成長，就能做出一些別人想不到的連線。

## 程式語言是思維的腳踏車

這是整期播客裡最值得記下的一句。

> "你可以走路，但你騎上腳踏車會快得多。程式語言就是思維的腳踏車。"（Chris Lattner）

他借的是 Jobs 那句"計算機是思維的腳踏車"，但把它挪到了語言本身。邏輯是這樣的：計算機擅長做特定的事，而人腦裡有一個想法，想讓它實現。從直接寫彙編，到高階抽象，到設計一個神經網路讓機器替你幹活，中間有無數個層次可以停。停在哪裡，就決定了你得到什麼、付出什麼。

這裡有個值得記住的判斷：**程式語言有兩條腿，一條是底層的機械部分，型別系統、編譯器、怎麼讓計算機高效跑起來；另一條是 UI，也就是語言和人之間的介面。**後面這條很多人不當回事，覺得無非是花括號、分號、空格還是 Tab，純主觀偏好。但 Lattner 堅持，UI 是一個設計問題，而且好的設計和壞的設計，人是能感覺出來的。

他的例子是 Swift。Swift 在底層有一堆好東西，同時在讓程式碼"感覺良好"這件事上投入了巨大的人力。這不是玄學。

具體怎麼讓語言感覺良好？他給了一套很實用的判斷標準。

- 樣板程式碼太多，你會覺得自己沒在產出，這是壞事
- 記憶體不安全，你會被懸空指標和各種 bug 纏住，除錯到懷疑人生，這也是壞事
- 把這些東西從體驗裡減掉，使用者就會更開心

但這裡有個陷阱。Stack Overflow 上那些高票答案，代表的是一小撮最活躍使用者的優先順序：安全的程式碼、規範的程式碼、穩定的程式碼。這不一定跟大多數普通使用者的體驗吻合。如果 99% 的人只關心"我想搭個 Web 伺服器把事辦了，多快能辦成"，那麼語言設計者就要清楚自己到底在為誰最佳化。

所以語言設計真正要回答的是兩個問題：**有哪些庫已經存在，以及你能多快把它們拼起來。**語法層面的爭論，在使用者到達目標的過程中只佔很小一塊。

## 值語義：同時解決正確性和效能的那個甜點

這是技術含量最高的一段，值得慢慢拆。

Lattner 用 Tensor（張量）舉了個例子。Tensor 就是一個多維數字網格，能做加減之類的運算。為什麼在 Python 裡你有時候必須顯式 clone 一個 Tensor？

原因是 Python 用的是引用語義。你手裡握著的是一個指標，它指向那個東西，你並沒有直接持有它本身。你把 Tensor 傳給一個函式，函式在裡面加了點東西，你回到外面一看，發現它也變了。更麻煩的是，你把 Tensor 交給某個物件，它把引用存進了字典裡，之後又往裡塞資料。你以為你只交出去一份，對方以為自己是唯一的持有者，誰也不知道背後發生了什麼。於是你只能 clone，因為你不確定自己是不是唯一持有者。

做機器學習、習慣用數學思維思考的人，會覺得這很反直覺。數學裡物件是按值傳遞的，Python 卻安靜地不這麼幹。等你 debug 到一半，才發現要搞清楚克隆發生在棧的哪一層，還得先讀懂那個庫的實現。這就是純粹的時間損耗。

Swift 用值語義解決了這個問題。

> "在 Swift 裡，Tensor 是一個值。你複製它，就看起來得到了一份獨立的複製。你改其中一份，另一份不會跟著變，因為你只是複製了它。"（Chris Lattner）

聽起來像每次操作都要付一次複製的代價。但 Swift 用了 copy-on-write：你傳一個陣列給函式，函式如果只是想讀，大家共享同一份記憶體；只有當某一方真的要改，系統才真正複製。傳出去的時候，如果只有一個引用，系統就知道可以就地更新，不用額外分配。

對比 Java。Java 的字串是不可變的，所以每次拼接都要分配一個新的物件來裝 x+y，因為別人可能還持有原來那個的指標。不可變性帶來的安全，代價是效能。純函式式語言在大量場景下都是這個模式。

Swift 的賭注是：**把值語義做成預設，同時用 copy-on-write 拿回效能，可以得到一個其他語言裡沒見過的甜點區。**

這個設計還有個更深的意圖。它讓數學在程式碼裡真的像數學一樣工作，同時又保留了程式設計師需要的底層效率。你不會為了正確性犧牲效能，也不會為了效能天天懷疑自己手裡的是不是唯一引用。

這就是"漸進式披露複雜性"的一個例項。Swift 允許你從 print("hello, world") 開始，不必一上來就寫 public static void main 加一堆訪問控制、包、類。你正常寫程式碼，預設是安全的、夠快的。等你成了高階使用者，想控制底層指標，可以去調 malloc，但沒人會在第一頁教程裡教你這麼幹。這種分層的能力，是 Lattner 認為程式語言設計裡最難也最有價值的部分。

## 語法糖之爭與一場卸任

訪談裡有一段關於 Python 3.8 引入 Walrus 運算子（海象運算子）的討論，非常有意思，因為它不只是技術問題。

Lattner 先定義了什麼算語法糖：把一個語言裡已經存在的東西，用一種更簡潔的方式寫出來。他隨即指出，這種特性最大的麻煩在於，它的價值幾乎完全落在主觀區間裡：**這件事發生的頻率到底高不高，值不值得為它引入新語法？**

他給了一個人類心理學的觀察。面對一個新東西，人們會系統性地高估學習它的負擔。它看起來很陌生，所以你抗拒。但如果它從一開始就在語言裡，你就會說"這當然是 Python 的一部分，我熟得很"。

Walrus 運算子引發的爭議最終導致 Guido van Rossum 卸任了 BDFL（終身仁慈獨裁者）的位置。Lattner 對這件事的解讀，視角比一般人深。

> "我從中得到的感受是，他把決策者的重量壓在了自己肩上，而且這件事和他人身份認同綁得太緊，所以他把它當成私人的事。他把自己放在了'那個人'的位置上，周圍卻沒有一個支撐結構。"（Chris Lattner）

他的類比很妙：創始人知道公司是怎麼一步步走到今天的，所以敢說"我們過去二十年都這麼幹，但今天我們換個活法"，然後推動整個公司轉型。但創始人走了之後，繼任者往往不敢做這種決定，哪怕 CEO 理論上什麼都能幹。

原因有兩個。

第一個是繼任者沒經歷過那些決策的過程，不知道當初的決策依據是什麼。一旦原則變了，你本該有義務改變做法、改變方向。但如果你不知道當初是怎麼走到這一步的，那一切就像福音書，你不會去質疑它。

第二個更狠：**即使你在理論上是大權在握的那個人，你也只是"自以為在掌權的人"。**你得去激勵團隊，得解釋、得讓人理解、得讓人真心認同。如果他們不信，方向就轉不過來。領導者能行使的權力，是有上限的。

Swift 的做法是用一個核心團隊來分攤這份重量，最終決策交給群體的智慧。這讓決定不那麼私人化，而且有公開的提案流程和決策理由記錄。Lattner 把這種機制類比成最高法院的判例法：每次決定都有據可查，既能指導未來的討論，又能充當一種防禦機制。有人不滿的時候，矛頭指向的是"這個決定"，跟"某個人做錯了事"脫鉤。

他也承認這個模式不完美。核心團隊的每個人都是不同的人，觀點不一樣，還有 Apple、Google、SiFive 三個組織在裡面。但正因為如此，從原則出發推導決定，再想辦法讓社群理解並認同，這條路才格外重要。

## LLVM 的二十年之癢，和 MLIR 的野心

LLVM 到 2020 年 12 月就滿二十歲了。Lattner 說這個專案正處在容易鈣化的年紀。

他的原話裡有一層很微妙的自省。他說自己的毛病是能看到 LLVM 的很多問題，這些問題一直硌著他，但他沒時間去修。時間久了，它們像指甲縫裡的沙子，你擺脫不掉。而別人看不到這些問題，也抗拒改變，於是"我們應該修這個"換來一句"聽起來風險很大"。

他提出了一個新框架：MLIR（Multi-Level IR）。名字是編譯器圈的人取的，取名水平堪憂，Lattner 自己都吐槽了。

MLIR 要解決的是什麼問題？編譯器歷史上都是為某個特定領域造一整套工具。LLVM 擅長 CPU，JVM 擅長垃圾回收語言加動態編譯，每個領域都從頭造一遍，大量的東西重複實現。

MLIR 提供一套通用的編譯器基礎設施，讓你能更快地為不同領域造出專用的編譯器，而且結果質量還不錯。它比 LLVM 更通用、更靈活，LLVM 反而是它的一個子集。目標領域包括自定義加速器、矩陣乘法硬體，以及一整個硬體綜合的世界，也就是用來設計電路的編譯器，編譯的領域是電晶體。

這裡有個關於社群文化的絕佳觀察。**MLIR 是由 Lattner 和一幫非常瞭解 LLVM 的人造的，所以他們修掉了 LLVM 裡的一堆歷史錯誤。但那些二十年來一直在維護 LLVM 經典部分的人，對新東西並不熟悉。新東西感覺上就是"不可信"的。**

他沒有為此憤憤不平。他覺得這種文化張力是健康的。思想會滲透，技術會擴散，人需要用自己的語言去重新理解一件事。這個過程很慢，但它在發生。

## RISC-V：把指令集從公司手裡拿出來

Lattner 現在在 SiFive 做平臺工程的高階副總裁。這家公司由 RISC-V 的三位創始人建立，其中就有 Dave Patterson。

RISC-V 的核心特徵是：它是一個開放標準。x86 只能由 Intel 和 AMD 造，ARM 的指令集只能由 ARM 公司授權出去，MIPS 歸某家公司所有再授權。RISC-V 誰都能拿來造晶片。

這聽起來抽象，但它解決的是一個非常現實的問題。過去幾十年裡，公司起起落落，指令集也跟著起落。Sun 的 SPARC 活到了今天，HP 的 PA-RISC 曾經承載了整個伺服器業務和大量客戶，後來 HP 決定轉向 Intel 的 Itanium，結果並不好。

真正的問題在這裡：**你在一個由某家公司擁有的指令集上投入了鉅額資金、大量工程和軟體工作，圍著它建了一堆產品，然後這家公司做了個技術決策或者商業決策，你就卡死了。**哪怕強如 Intel，也不能保證每次都執行到位。

RISC-V 提供的是可選性。你從 SiFive 買一個實現，如果二十年後 SiFive 出了什麼問題，沒關係，你可以從別人那裡買 RISC-V 核。整個生態裡有人在造不同權衡的核。你有產品家族、有多種需求，大機率能在 RISC-V 空間裡找到合適的東西。

Lattner 的展望是：**未來會出現大量定製晶片。**眼下的局面是，一家做智慧硬體的公司如果沒有 iPhone 那樣的出貨量，就負擔不起定製晶片，只能買別人設計的、並不完全貼合自己需求的現成貨，為用不上的矽付錢。如果設計晶片的成本降下來，定製晶片就會變多，電池續航會更好，方案會更貼合具體場景，上市速度會更快。

## 摩爾定律：三種解讀，都沒錯

訪談裡把 Dave Patterson、Jim Keller 和普通人對摩爾定律的理解擺在一起。

Jim Keller 說物理上還有上千倍的空間，電晶體還能更小更快。Lattner 認為他說得完全對，我們還沒撞到物理極限。但那不是摩爾定律本來的意思。

摩爾定律的原始表述裡有一個明確的經濟維度：單位面積的成本，以及那個空間裡最經濟的點。Dave Patterson 常強調的正是這一點。按這個技術性的定義，摩爾定律確實變了。

Lattner 又給了第三種解讀：單執行緒效能不再像以前那樣提升了。以前你買一顆奔騰 66，前一年是奔騰 3，效能翻倍，而且是在做完全相同的事情時翻倍。同樣的程式跑快一倍，你只要開張支票等一年半。很多人心裡的摩爾定律就是這個，而這個已經死了。

取而代之的是什麼？是逼著人換程式設計方式。你得寫 CUDA 才能拿到 GPU 算力。你得習慣一臺機器上有 50 個核、100 個執行緒。你有專為機器學習做的加速器。效能還在，但你得改程式設計模型。

而一旦談到改程式設計模型，就繞回語言問題了。C 語言是為 CPU 設計的，想跟 GPU 說話，你得去用它的表親 CUDA，那是一套不同的工具、不同的世界、不同的思維方式。現在還沒有一個能統一縮放的世界，Lattner 覺得可以有一個，而且會好得多。

## 讓並行成為語言的一等公民

聊到機器學習為什麼能自動並行，Lattner 指出了一個漂亮的轉折。

讓一個 C 編譯器或 Swift 編譯器自動並行化命令式程式碼，還要推理所有指標，是非常難的問題。但換到機器學習的領域，那些做貓檢測器的人，順手搞出了一個極其強大的抽象層：一組可以拼裝的運算元。抽象層次被抬得足夠高，自動並行化的編譯器就突然可行了。你可以用 TensorFlow 寫一個模型，讓它在 1024 個 TPU 節點上跑。

> "這套東西出自那些只想解決問題的人，加上社群的有機演化，程式語言圈的人並沒有參與。"（Chris Lattner）

批次處理（batching）也是同一個道理。一個很樸素的想法，但威力巨大。

他自己寫的《Swift 併發宣言》是另一種思路。寫宣言的原因是，Swift 社群需要小而精細的提案，一次只推進一小步，但同時又需要大的方向。當你在做一件大事卻要拆成小步走的時候，怎麼知道不是在隨機遊走？宣言就是那個把大圖景畫出來、讓後續的小步有參照的東西。

宣言裡的核心思路有幾層：

- 多個計算機或多個執行緒通訊時，最好是非同步的。所以要能分別執行，再互相通訊，這意味著需要建模非同步通訊的機制，比如 async/await
- 往上一層是記憶體安全。兩個執行緒同時碰同一塊記憶體就是競態條件，這種 bug 讓人抓狂，因為通常無法復現。值語義在這裡又派上用場，因為數學和複製在併發世界裡同樣成立
- 再往上是給程式設計師的心智模型。宣言提出的方案是一個老模型的新版本：actor。邏輯上，你寫的是一塊單執行緒的孤島，它跟其他東西非同步通訊
- 繼續往上，這些非同步通訊的東西不共享記憶體，那它們為什麼必須在同一個程序裡？可以跨程序，可以跨機器。於是你得到一條通往分散式程式設計的平滑路徑
- 再往上，加速器本質上是非同步的東西，你透過發訊息跟它通訊。怎麼給它們程式設計，這就很有意思了，而且不在提案範圍內

這裡有一個貫穿全篇的設計哲學問題：**多少該是魔法，多少該交給人控制？預設情況錯了的時候你怎麼辦？**

Lattner 舉了 Logo 作為反面例子。很好上手，專為教小孩設計，但你很快會撞到天花板，上不去了。只能換一個世界，重寫所有程式碼。Python 的併發也有類似的困境：全域性直譯器鎖讓多執行緒很麻煩，你寫了一定規模的程式之後，會發現自己被一系列糟糕的權衡困住。

他的偏好很明確：**建一個能講清楚的簡單模型，同時留一個逃生艙。**Swift 裡預設你按標準寫法寫就不會踩坑，但如果你非要拿一個 C 級別的指標，可以顯式去做。預設有護欄，護欄外有通道。

至於誰來決定程式碼的哪部分並行？在他的提案裡是程式設計師。執行時和編譯器要非常可預測。這跟歷史上那批試圖自動並行化的編譯器形成對比。

那些編譯器專案很有誘惑力：不改一行程式碼，換個編譯器就快十倍，編譯器會做模式匹配、深度分析，把結構體陣列轉成陣列結構體之類的。麻煩的是，你加個功能、重構一下程式碼，突然效能掉了十倍。因為某個函式沒被內聯，你觸發了編譯器的某個啟發式失效。

> "作為使用者，你不想知道，你不想知道編譯器怎麼工作、記憶體層次怎麼工作、它怎麼被並行化的。你希望這些被抽象掉。但一旦魔法失效，你就掉下懸崖，不知道該怎麼辦。"（Chris Lattner）

如果你在乎效能，可預測性就極其重要。

## GPT-3 和 Software 2.0 的邊界

Lattner 對 GPT-3 的反應分兩面。一面是，把模型做大、把資料塞得更多，只要訓練方法對、架構好，結果就更好，這在深度學習圈早就被理解透了，所以 GPT-3 本身不算意外。另一面是，讓它真正跑起來需要海量的工程投入。

他提到 OpenAI 那篇引發討論的部落格：因為擔心被濫用造成社會傷害，所以不釋出。他認為這個擔憂至今成立。用意良好的工具可以被用在很可怕的地方，影響可以非常深遠。

關於 Andrej Karpathy 提出的 Software 2.0，也就是用學習模型替代越來越多的命令式程式碼，Lattner 的態度是：**部分同意，但他把它看作一種新的程式設計正規化，跟 Software 1.0 是並列關係，談不上替代。**

他給了一套很清晰的判斷。機器學習解決某幾類問題極其出色，而且是唯一正確的方式：

- 你不會再用 C 程式碼去寫一個貓檢測器你不會再用 C 程式碼去寫一個
