2026 年 3 月 16 日,GPU 編譯器 Triton 收到一個 PR,標題說要修好 RTX 5070 Ti/5080/5090 這批消費級 Blackwell 顯卡的隨機當機(「segfault」)。它有完整描述、有測試,自動 review bot 留了意見,維護者要求修改,作者也照改了。同一天核准,同一天合併。

隔天,一位審查者 在 PR 底下客客氣氣地留言:這個 PR 很可能不正確,描述也不準確,而且整個修法賴以成立的那句前提,本身就是錯的。

當天維護者就把它撤回,理由只有一句:「Based on Nvidia’s feedback this doesn’t seem to be a correct PR」(根據 NVIDIA 的回饋,這個 PR 看起來不正確)。從合併到撤回,大約一天。

這個 PR 的 commit 帶著 Co-Authored-By: Claude Opus 4.6,是 AI coding agent 的作品。但這個故事有意思的地方,不在 AI 寫錯,而在 review 流程每一關都有人在場、也真的抓到東西,最要命的那一個錯卻一路走進了主幹。

SemiAnalysis 配的字幕,比留言本身兇

這件事會被看見,是因為 SemiAnalysis 在 X 上發了一則大寫開頭的「AI CODING SLOP ALERT」。他們的警告是:在開源專案裡,AI coding agent 產出的垃圾跟有價值的 diff,越來越難分辨。接著拿 Triton PR #9734 當例子,說它宣稱修好沒有 TMEM(張量記憶體)的消費級 Blackwell,但仔細看根本沒修好;合併之後,NVIDIA 的 PyTorch 技術主管「以非常 PROFESSIONAL 的方式」留言說這個 PR 完全是 slop。

那個全大寫的「PROFESSIONAL」是 SemiAnalysis 自己在酸。PR 頁面上那則留言是一段客氣、純技術的說明,「slop」是 SemiAnalysis 替它配的字幕。至於留言者是 NVIDIA PyTorch 技術主管,這是 SemiAnalysis 的說法,PR 頁面本身沒標示所屬。

推文還特地補了一句:這位技術主管是一台「2024 Honda Civic Sport Edition」的車主。這條資訊對判斷 PR 對不對毫無幫助,推文也沒解釋為什麼要寫,Mogu 決定尊重 SemiAnalysis 的創作自由,不替它腦補 ┐⁠(⁠ ̄⁠ヘ⁠ ̄⁠)⁠┌

Mogu 想補充:

我對 SemiAnalysis 這個標題有點意見。「slop」這個詞很好轉傳,但它不帶任何資訊:說一個 PR 是垃圾,沒告訴任何人錯在哪。真正讓 Triton 在一天內撤回的,是那則被酸成「很 PROFESSIONAL」的留言,它講清楚哪句前提錯、拿 CUTLASS 跟 PyTorch 當證據、附上編譯失敗的錯誤訊息。諷刺的是,對付 AI 量產的低資訊 PR,最有效的武器剛好是一段高資訊、不嗆人的人類留言。


PR 改的是標籤,不是路

要看懂錯在哪,得先知道 PR 想修什麼。

sm_120 是消費級 Blackwell 的架構代號。Triton 編譯 GPU 核心程式時,會把架構字串交給 NVIDIA 的組譯器 ptxas。字串尾巴多一個「a」(例如 sm_90a、sm_100a),意思是「這份程式碼只給這一款架構跑,可以用它的專屬指令」。可以把它想成貼在包裹上的一張標籤:標籤寫什麼,組譯器就放行哪些指令。

PR 描述的診斷是這樣:消費級 Blackwell 會隨機當機,因為編譯器替一塊不存在的硬體產生了張量記憶體指令(tcgen05)。描述接著宣稱,「a」這種標籤只存在於 sm_90 跟 sm_100,sm_120a 根本不是真的編譯目標。

原始版本提了三項改動:sm_120 不加「a」、改 PTX .target 的正規表示式、把 sm_120 改走 Hopper 那條編譯 pipeline。用剛剛的比喻講,就是一次撕標籤、改分揀規則、再改走另一條路。

review 之後,維護者要求把改路線跟改正規表示式兩項撤掉,判斷條件改成 capability != 120,讓未來的新架構預設還是加「a」。作者照辦。所以最後合併進主幹的核心改動只剩一件:把 sm_120 的標籤從 sm_120a 撕成 sm_120,外加一段程式註解,宣稱 sm_120a 會導致張量記憶體指令,以及改過的測試。PR 描述沒更新,還寫著原本那三項改動。

如果「sm_120a 不存在」這句是對的,撕標籤很合理。問題就在這句。

隔天那位審查者指出,120a 是真的「arch-conditional」編譯目標,CUTLASS 跟 PyTorch 都在用 sm_120a。他還回報,用這個 commit 編譯會撞上 ptxas 錯誤:tensormap.replace not supported on .target sm_120。翻成標籤的話:說明書宣稱這款型號沒有這張標籤、貼了是印錯,結果 CUTLASS 跟 PyTorch 早就貼著這張標籤在用;標籤撕掉之後,還有指令因為少了它而被組譯器擋在門外。


review 抓到的,跟沒抓到的

把時間線攤開,3 月 16 日那天其實有人在認真看。

自動 review bot(OpenAI Codex 的自動 review 工具)留言之後,作者把 sm_120 的測試從逐元素相加換成 tl.dot 矩陣乘法。原本那個測試不管編譯目標是什麼,都不會產生 tcgen05 指令,斷言等於什麼都沒驗。維護者則砍掉了兩項範圍過大的改動,還顧到未來架構的預設行為。

空心測試、改動範圍、未來相容性,這三個都是真的問題,也都被修了。它們有個共同點:只要盯著這個 repo 跟這份 diff,就看得出來。

沒人問的那一題是「sm_120a 到底存不存在」。這題的答案不在 Triton 的 repo 裡,在 CUTLASS 跟 PyTorch 的程式碼裡,在知道 NVIDIA 工具鏈怎麼運作的人腦袋裡。PR 描述把它寫成一句篤定的事實,整個修法都建立在上面,而它是整份 PR 最需要查、也最少人有能力查的一句。

Mogu 的看法是:要怪審查者也不太公平。review 本來就是拿 PR 給的前提去檢查實作,前提寫得越完整、越有自信,審查者越自然地把力氣花在「這個實作有沒有照前提做好」,而不是「前提本身對不對」。AI 寫出一段篤定的技術描述幾乎不花成本,能一眼看穿前提錯誤的領域專家卻很稀缺;這次那個人是在合併之後才出現的。gu-log 之前寫過 Mitchell Hashimoto 推出 Vouch,講的是 AI 讓任何人都能產出看起來像樣的貢獻,開源靠寫 code 的門檻篩人的老辦法失靈;Triton 這次再往前一步,連「寫出一段看起來很懂的診斷」的門檻也不見了。

Mogu 溫馨提示:

這件事我有切身之痛。你現在讀的這篇是重寫版:前一版把 SemiAnalysis 的酸寫成當事人原話,還把 PR 的機制畫成一個來源沒講過的故事,文筆順、笑點足,在站上掛了半年多。後來有人回頭把 PR 時間線一則一則對過,才發現開場跟主軸都蓋在錯的前提上,只好整篇打掉重寫。那一版上線時沒有被人回頭翻過原始紀錄;這種錯,光看文章本身順不順是看不出來的。寫文章跟寫 PR,栽在同一個地方 (⁠。⁠◕⁠‿⁠◕⁠。⁠)


連 bug 存不存在都沒結論

故事還有個尾巴。3 月 25 日,另一位貢獻者開了 PR #9852,認為 #9734 只處理了後綴、沒處理編譯路線,於是除了拿掉後綴,還把 sm_120/sm_121 改走 Hopper 那條路線。維護者回覆說,大家一直都在 sm_120 上正常使用 Triton,而且這個 patch 跟被撤回的那個差不多。作者自己在 SM121 上實測,發現 sm_121a 能用、編譯結果裡也沒有張量記憶體指令,承認原本的診斷錯了,3 月 26 日自行關閉,沒有合併。

所以到最後,連「消費級 Blackwell 上到底有沒有那個當機問題、根因是什麼」都沒有乾淨的結論。#9734 撕掉一張其實存在的標籤,去修一個可能根本沒被確認過的 bug,然後 #9755 把標籤貼了回去。

SemiAnalysis 說 slop 跟有價值的 diff 越來越難分辨。Triton 這次的經驗是:分辨得出來,但分辨的成本落在一個很特定的人身上,那個知道 CUTLASS 裡寫著 sm_120a 的人。這次他在一天內出現了,沒收任何費用,也不是合併前排好的任何一關。下一份帶著篤定前提的 PR,會繼續預支這種人的時間,而目前沒有誰在付這筆帳。