![]()
機器之心編輯部
試想一下,如果把當下大火的大模型技術帶回 1970 年,會發生什么?
彼時,沒有 GPU、沒有 CUDA,也沒有浮點數,甚至沒有任何深度學習框架,只有一臺 PDP-11 小型機,以及一門幾乎已經退出歷史舞臺的語言:匯編語言。
近日,一位開發者給出了答案。他復現了那個年代的技術環境,用 1970 年代的 PDP-11 匯編語言,實現了一個 Transformer,并且真正訓練成功了,這個項目叫做 ATTN-11。
具體來看,就是在 1970 年代的小型機 PDP-11 上,用純匯編語言,實現一個單層、單頭的 Transformer,并完成一個「序列反轉」的任務,即輸入一串數字,輸出其反序結果。
比如,輸入:4 7 4 9 6 3 6 5,輸出:5 6 3 6 9 4 7 4。
看似很容易,但關鍵特征是,機器無法通過「記住內容」來完成這個任務,必須理解「位置之間的映射關系」。而這恰恰是自注意力(Attention)機制的的核心能力。
項目結果顯示,在一臺 1970 年代的計算機上,一個僅有 1216 個參數、單層單頭的 Transformer,在約 350 步訓練后就實現了 100% 的準確率,而訓練時間只有 5 分鐘左右。
有意思的是,由于 PDP-11 時代,程序的主要存儲介質是 Paper Tape(穿孔紙帶),因此,該項目開發者又稱該項目為「Paper Tape is All You Need」。
![]()
而當開發者將該項目發布之后,引起了網友的熱議。
當下,大模型的發展主要圍繞 Scaling Law 展開,更多的參數 ,更多的數據,更的多算力…… 而 ATTN-11,卻在極低的資源、極簡的結構下,成功實現功能閉環。因此,大家不禁在思考:Transformer,到底需要什么?
一位網友該項目「在 PDP-11 上訓練只要 5 分鐘」表示驚訝,而更讓他震驚的是,這似乎說明「我們其實一直都可以做到這些???」
![]()
另一位網友則認為,不必驚訝,是的,我們一直可以做到這些。因為,「1980 年代的 Cray 超級計算機非常厲害,尤其在矩陣乘法方面性能極其強大。
比如一臺 1984 年的四核 CPU Cray X-MP,可以持續提供 800 MFLOPS 到 1 GFLOPS 的算力,如果配上一塊 1GB 的 SSD,在算力和帶寬上已經足以在半年內訓練一個 700 萬到 1000 萬參數的語言模型,并以每秒 18 到 25 個 token 的速度進行推理。
而到了 1990 年代中期,一臺 Cray T3E 的算力,就已經可以承載 GPT-2(1.24 億參數)規模的模型,這要比 OpenAI 早 24 年。
而我自己,甚至還用一臺 1965 年的打孔卡計算機,通過反向傳播學會了 XOR。
真正的瓶頸從來都不是硬件,而是想法。」
![]()
另一位網友也現身說法,他舉了后量子密碼學的例子。他表示,基于格(lattice)的加密方案早在 1990 年代就已被提出,但真正走向產業落地,卻花了整整幾十年,而問題的關鍵不在于數學不成熟,也不在于硬件不足,而是讓這些理論真正「跑起來」的關鍵思路,當時還沒有出現。
![]()
接下來,詳細了解一下具體項目實現。
開發者稱,該項目是 Xortran 的精神續作,Xortran 是一個在 IBM 1130(1965 年)和 PDP-11/20(1970 年)上,用 Fortran IV 實現反向傳播來學習 XOR 運算的神經網絡。
自然而然地,下一步就想看看這些機器是否能在可接受的時間內(幾小時)成功訓練一個小型 Transformer。
從架構上看,Transformer 實際上只是基礎神經網絡的適度擴展。矩陣乘法、反向傳播、隨機梯度下降(SGD)和交叉熵等構建模塊早已存在。
新增的三個部分是:
- 自注意力:映射后的查詢(Query)與鍵(Key)之間的點積得分;
- 位置編碼:學習到的位置嵌入,加到輸入上;
- Softmax:將得分轉換為概率分布;
該項目的目標是訓練一個 Transformer 來反轉數字序列。盡管看似簡單,但對神經網絡來說,模型必須學會將每個 token 路由到僅由其索引決定的位置,沒有基于內容的捷徑。而這類問題正是為自注意力設計的,實際上也是 Tensor2Tensor(谷歌 2017 年原始 Transformer 的參考實現)中包含的算法基準之一。
架構
數據路徑很直接,token 被嵌入,通過帶有殘差連接的自注意力層,然后映射回詞表并通過 softmax 得到預測:
![]()
![]()
該模型是一個極簡的 Transformer:嵌入、帶殘差連接的自注意力、輸出映射。它是真正的帶自注意力的 Transformer,但既不是 BERT 也不是 GPT:沒有層歸一化、沒有前饋網絡、沒有解碼器。
該任務中,不需要對 token 表示做任何變換,因此注意力和殘差連接就足夠了。層歸一化在深層網絡中用于防止激活漂移,但在單層中并不需要。
針對 1970 年代硬件的優化
第一次實現沿用了 Xortran 的方案,并使用 Fortran IV 編寫。在統一學習率為 0.01 的情況下,模型完成 100 步訓練需要 25 分鐘,而要達到 100% 的準確率則需要約 1500 個訓練步數。這在真實硬件上大約相當于 6.5 小時的訓練時間,在 IBM 1130 上甚至可能需要整整一周。
即便是按照 1970 年代的標準來看,這樣的耗時也是難以接受的,因為當時的計算機通常采用分時共享機制,計算資源非常寶貴。
因此,第一次改進是將統一學習率替換為手動調優的分層學習率:
![]()
編碼「反轉模式」的注意力權重更適合使用較高的學習率,而輸出映射層在較小學習率下收斂效果更好。通過這一調優,訓練步數降至 600 步,預計訓練時間約為 2.5 小時。
優化器采用的是最基礎的隨機梯度下降(SGD)。像 Adam 這樣的優化器雖然可以為每個參數自適應調整步長,但代價是每個權重需要額外維護兩個狀態向量,使參數所占內存增加到原來的 3 倍。同時,每次更新還需要進行平方根和除法運算,即便在配備 EIS 的 PDP-11 上,這些操作也依然開銷較大。
相比之下,分層學習率在不增加額外成本的情況下實現了類似效果,而且由于模型規模較小,這三組學習率可以手動調優。此外,這也使得 Transformer 可以裝入 32KB 的核心內存,而不是 64KB,這在 1970 年代尤為關鍵。
補充說明:由于采用裸機匯編實現,ATTN/11 的內存占用并不高于 Xortran,后者還需要承擔 RT-11 V3 操作系統和 Fortran 運行時的開銷。最終生成的二進制文件也相當緊湊,僅為 6179 字節。
NN11
核心算術運算基于 NN11,這是一個為 ATTN/11 和 PDP-11 設計的最小化定點神經網絡計算棧。
NN11 的組織結構類似于 BLAS,分為多個層級:最底層是標量基礎操作(FXMATH);其上是向量運算,如點積和縮放(VECOP);再往上是矩陣–向量運算(MATOP),每一層都構建在下層之上。
此外,還有兩個模塊將該計算棧擴展到線性代數之外:一個是激活函數及其查找表(ACTFN),另一個是層級操作(LAYER),用于將前述運算組合起來,實現、映射以及注意力等功能。
這些算術計算會根據不同的計算階段進行適配:
![]()
在 PDP-11 上,前向計算使用 Q8、反向傳播使用 Q15 的組合非常契合:將一個 Q8 數與一個 Q15 數相乘,會在一個 32 位寄存器對中得到 Q23 的結果,只需一次「ASHC #-8」操作即可將其縮放回 Q15。
因此,反向傳播中的乘法開銷并不高于前向計算,同時還能讓梯度的精度達到激活值的 128 倍。
經過優化后,模型在 350 步內即可收斂,使得在開發者的 PDP-11/34A 上,總訓練時間縮短至僅 5.5 分鐘。
![]()
在該項目中,開發者并沒有使用真正的紙帶讀取器,因此是通過控制臺將目標代碼直接寫入內存。
以下是運行該 Transformer 后的結果:
![]()
原型
在正式轉向匯編實現之前,必須先驗證其正確性。因此,開發者先在 Sheaf 中對浮點和定點算術進行了原型設計與驗證。Sheaf 是開發者開發的一個函數式 ML 框架,內置了可觀測性機制。
對于這類機器學習工作,Sheaf 相比 Python 有幾個優勢:
- 代碼量大約減少三分之一;
- 其純函數式語義帶來了更強的正確性保障;
- 能夠對每一個中間張量進行內置追蹤,包括其形狀、數值范圍以及計算時間。在開發定點算術時,這一點尤為關鍵。
例如,在「vtmul」上設置一個范圍保護,可以立刻捕捉到遺漏「>>8」位移的問題:
![]()
浮點與定點兩種原型實現都可以在「proto」文件夾中找到,同時還包含最初的 Fortran 版本。
實現細節
由于沒有浮點運算單元,超越函數(如 exp、log)被預先計算的查找表所替代。在 PDP-11 上,一次查表只需一條「MOV」指令,其開銷遠低于多項式近似或 CORDIC 算法。
Softmax
Softmax 使用一個包含 256 個條目的查找表(EXPTBL,Q8),將每個索引 i 映射為 exp (?i/32)。計算分為三個步驟:
- 找到輸入向量中的最大值,并從每個元素中減去該值,以保證數值穩定性;
- 將差值(max ? x_i)除以 8,作為查表索引,并限制在 [0, 255] 范圍內;
- 將得到的 exp 值除以它們的總和(通過 FXDIV),得到概率分布。
該查找表大約覆蓋了輸入范圍內的 8 個單位,在趨近于 0 之前,這對于一個 10 類詞表來說已經完全足夠。
交叉熵損失
損失函數每 50 步計算一次,用于報告訓練過程。它依賴另一個查找表(LOGTBL,257 個條目,Q12),將每個值 x ∈ [0, 256] 映射為 ?ln (x/256) × 4096。
計算流程遵循標準路徑:先對 logits 做 softmax,讀取目標 token 的概率,然后在查找表中查得 ?ln (p)。8 個位置(每個序列位置一個)的結果累加到一個 32 位寄存器對中(因為 8 個 Q12 值的和可能超過 16 位),再通過「ASHC #-3」除以 8。Q12 精度(1/4096 ≈ 0.0002)可以提供四位小數,足以用于監控收斂過程。
查找表
ATTN/11 使用兩個查找表。第一個將每個索引映射為 Q8 表示的 exp (?i/32),在 softmax 中用一條「MOV」指令替代指數計算。另一個表主要用于便利計算,將每個值映射為 Q12 表示的 ?ln (x/256),每 50 步用于計算交叉熵損失,以監控模型收斂情況。
![]()
兩個查找表均通過 Sheaf 腳本離線生成,并以 .WORD 常量的形式存儲在源代碼中。
交叉熵梯度
反向傳播利用了 softmax 與交叉熵組合的一個經典性質:logits 的梯度可以簡化為
![]()
從而在訓練過程中完全避免了對數運算的開銷。該結果最初以 Q8 表示,隨后左移 7 位轉換為 Q15,這是整個反向傳播過程中使用的數值格式。同一個 SFTMX 例程同時用于前向與反向計算,無需單獨實現反向傳播版本。
最后補充一點:在這些算法的開發過程中,開發者僅將 AI 工具作為輔助使用,而所有的設計決策、縮放策略,以及數值驗證,均是在硬件上由人工完成的。
內存布局
ATTN/11 總共占用 19.2 KB 內存。下表展示了其內存分布情況,整理自 MACRO-11 匯編器的輸出列表:
![]()
這 1216 個參數由于計算需要被復制了三份:Q16 累加器(4.8 KB)、用于前向計算的 Q8(2.4 KB),以及用于梯度的 Q15(2.4 KB)。僅模型本身就占用了 9.6 KB,是整體內存使用中占比最大的部分。
構建
構建所需的兩個條件是:MACRO11 匯編器,以及用于將目標代碼轉換為可加載二進制文件的 obj2bin 工具。
![]()
運行
運行,需要具備以下條件之一:
- 一臺真實的 PDP-11,且其 CPU 支持 EIS 指令,并配備 32KB 的核心內存或 MOS 內存;
- 或使用 ll-34:這是我設計的一款電路級、微周期精確的 PDP-11/34 模擬器,可作為真實硬件的數字復刻。
ll-34 幾乎可以視作擁有一臺真正的 11/34。啟動 ATTN/11 的方式如下:
![]()
或者,如果只是想快速體驗,可以使用這里提供的 WebAssembly 版本:
- https://dbrll.github.io/ll-34/。
SIMH 也可以使用,但它模擬的是 PDP-11 的高層行為(而非電路級),并以宿主機 CPU 的速度運行。雖然可以通過人為方式降低速度,但其時序并非周期級精確,因此不太適合用于性能調優或還原真實體驗。
大家詳細了解該項目后有何感想,可以在評論區留言交流!
https://github.com/dbrll/ATTN-11?tab=readme-ov-file#attn11---paper-tape-is-all-you-need
https://news.ycombinator.com/item?id=47518568
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.