為什么要純C語言手搓GPT-2,Karpathy回應網友質疑
幾天前,前特斯拉 Autopilot 負責人、OpenAI 科學家 Andrej Karpathy 發布了一個僅用 1000 行代碼即可在 CPU/fp32 上實現 GPT-2 訓練的項目「llm.c」。
llm.c 旨在讓大模型(LM)訓練變得簡單 —— 使用純 C 語言 / CUDA,不需要 245MB 的 PyTorch 或 107MB 的 cPython。例如,訓練 GPT-2(CPU、fp32)僅需要單個文件中的大約 1000 行干凈代碼(clean code),可以立即編譯運行,并且完全可以媲美 PyTorch 參考實現。
項目鏈接:https://github.com/karpathy/llm.c
項目的 Star 量不到七個小時就沖上了 2000,目前已經接近一萬 Star。很多網友驚呼太強了:「即使頂著指針 ptsd,我也能感受到這些代碼的美。」
然而,llm.c 項目收到的不只是稱贊,還有很多質疑的聲音。例如,有網友直接提問:「能具體描述下這個項目做了什么嗎,解決了什么問題?」
對此,Karpathy 今天正面回應了網友們的疑問,詳細闡述了 llm.c 項目的意義是什么,優缺點有哪些。
機器之心對 Karpathy 敘述原文進行了不改變原意的編譯、整理,我們來看下 Karpathy 是怎么說的:
訓練大型語言模型 (LLM),例如 ChatGPT,涉及大量代碼,復雜度很高。例如,典型的 LLM 訓練可能會使用 PyTorch 深度學習庫。PyTorch 本身就相當復雜,因為它實現了:
- 一個非常通用的張量抽象(一種排列和操作數組的方法,這些數組用于存儲神經網絡參數和激活);
- 一個非常通用的反向傳播 Autograd 引擎(訓練神經網絡參數的算法) ;
- 在神經網絡中使用的大量深度學習層。
PyTorch 項目有 11449 個文件中的 3327184 行代碼。最重要的是,PyTorch 是用 Python 編寫的,Python 本身就是一種非常高級的語言 —— 必須運行 Python 解釋器將訓練代碼轉換為低級計算機指令。例如,執行此轉換的 cPython 項目包含 4306 個文件中的 2437955 行代碼。
llm.c 項目旨在移除所有這些復雜性,并將 LLM 訓練簡化為其最基本的要素,用非常低級的語言 (C 語言) 直接與計算機對話,并且沒有其他庫依賴項,唯一的抽象是匯編代碼本身。
令人驚訝的是,訓練像 GPT-2 這樣的 LLM 實際上只需要在單個文件中使用大約 1000 行 C 語言代碼。我通過直接在 C 語言中實現 GPT-2 的神經網絡訓練算法來實現這種壓縮。這實際上很困難,因為你必須詳細了解訓練算法,能夠導出所有層反向傳播(backpropagation)的 forward pass 和 backward pass,并非常仔細地實現所有數組索引計算,因為沒有可用的 PyTorch 張量抽象。但一旦這樣做了,并且通過再次檢查 PyTorch 來驗證正確性,你就會得到一些非常簡單、小且精致的東西。
那么,為什么人們不一直這樣做呢?
第一:這放棄了很大的靈活性。如果你想改動神經網絡,在 PyTorch 中你可能只需要更改一行代碼。而在 llm.c 中,改動很可能會涉及更多代碼,可能會更加困難,并且需要更多專業知識。例如。如果涉及一個新的操作,你可能就需要做一些微積分,并寫出它的 forward pass 和 backward pass 以進行反向傳播,并確保其在數學上是正確的。
第二:放棄速度,至少一開始是這樣的。天下沒有免費的午餐 —— 不應該指望僅 1000 行代碼就能達到最先進的速度。PyTorch 在后臺做了很多工作,以確保神經網絡非常高效。不僅所有張量操作都非常仔細地調用最高效的 CUDA 內核,而且還有 torch.compile 等等,以進一步分析和優化神經網絡并有效地在計算機上運行。
現在,原則上,llm.c 應該能夠調用所有相同的內核并直接運行。但這需要更多的工作,就像上述第一點一樣,如果更改神經網絡或正在運行的計算機的任何內容,你可能必須使用不同的參數調用不同的內核,并且可能會手動進行更多更改。
總的來說,llm.c 是訓練 GPT-2 的直接實現。這個實現結果出人意料地簡短。但 llm.c 不支持其他神經網絡,僅支持 GPT-2,如果你想更改神經網絡的任何內容,則需要專業知識。幸運的是,所有最先進的 LLM 實際上與 GPT-2 根本沒有太大的區別。并且,llm.c 必須進行額外的調整和完善,但原則上我認為它應該幾乎能夠媲美,甚至超越 PyTorch,因為我們消除了所有開銷。
最后,我為什么要做這個工作?因為這很有趣。它也很有教育意義,因為只需要那 1000 行非常簡單的 C 語言代碼。它只是一些數組和對其元素進行一些簡單的數學運算,例如 + 和 *。對于正在進行的更多工作,它可能會變得實際有用。