vatt'ghern jaskier's ballads

Steve Weis 找 Anthropic 要來兩個禮拜、1024 顆 GPU 的資源,摩拳擦掌要去解開 RSA-260——結果被別人先解開了。解開的那組人事後算了一筆帳:整條 GNFS 管線跑完,花了 4,900 個 GPU-day,換算市價大約四十萬美元。

RSA-260 倒下,帳單是四十萬美元

這篇文章要說的是 RSA-260——一個 260 位數的 RSA 挑戰數——怎麼被拆成兩個質因數,以及拆開它的那套工具鏈:一套大幅改寫過的 CADO-NFS、一顆叫 glas 的 GPU 格篩器,還有一個幾乎全程自己排程、自己抓效能瓶頸的 Devin agent。拆解用的仍然是同一套演算法(general number field sieve,簡稱 GNFS)——過去打破 RSA 分解紀錄用的都是它。改變的是把演算法裡最貴的一段搬上 GPU 要花多少工程力氣——答案從「原本很可能得靠一個團隊好幾個月的專業工程」,落到 Eric Lu 一個人邊設優先序、邊跟 Devin 來回對話,十幾天內跑完全程。

上一次紀錄停在 2020,這次比賽誰都不知道終點在哪

RSA-260 屬於 RSA Factoring Challenge——一系列公開的合成數,用來量測「拆開 RSA 這件事」目前實際上有多難做到。Eric Lu 自己形容這次的動機很輕:「過去幾週,Cognition 研究團隊和我一直在優化我們的 job scheduler,好更善用 disaggregated compute。作為一個概念驗證,也因為過去十年左右我一直把分解數字當興趣在玩,我指揮了一群 Devin 去拿下 RSA-260 的分解。」不是一個 Devin,是「一群」——原文字面上用的就是複數。「概念驗證」和「興趣」這兩個詞放在一個打破公開密碼學紀錄的專案旁邊,反差本身就是這篇文章想傳達的重點之一:RSA-260 是排程優化的副產品。

上一個公開紀錄停在 2020 年 2 月,RSA-250 被拆開之後,往下一個數字——RSA-260——沒有人再往前推進。六年後,社群裡幾組人幾乎同時衝向終點。9 月 8 日,工程師 gslin 在自己的部落格記錄下賽前的公開討論:已知 RSA-250(829 bits)花了 2,700 core-year,用同一套 GNFS scaling law 往上推,RSA-260(862 bits)的粗估落在 3,400 到 4,100 core-year 之間;但只要把格篩這段搬上 GPU,各方算出來的答案幾乎收斂到同一個數字——估計可以砍到 25 GPU-year。

這個「25 GPU-year」不是紙上談兵,是好幾組人拿去申請算力的依據。Steve Weis 找 Anthropic 要來兩個禮拜、1024 顆 GPU 的資源,如果全部跑滿大約值 39 GPU-year——理論上比 25 GPU-year 的估計還寬裕。結果,按 gslin 的記錄,這組配置「被其他人先完成了」。他的部落格沒有點名贏家是誰,只留下一句:也有其他競爭對手進入到最後階段。

這也是 gslin 轉述完整過程之後,自己覺得最值得琢磨的一點:「比較好奇的反而是 GPU 版本的 GNFS 一直都沒人 porting,直到 AI 時代才有人跳進去」。格篩搬上 GPU 早不是秘密,問題是誰願意花好幾個月時間去寫、去調。

贏家是誰,答案一天後揭曉。9 月 9 日,Eric Lu 在 Cognition 的部落格貼出完整的拆解過程與帳單——RSA-260 已經被拆開,而且不是靠 39 GPU-year 那個等級的算力堆出來的。

這不是 Eric Lu 第一次動手:在 RSA-260 之前,他已經拆過一個「C311」——難度大約相當於對一個 216 位數的數字跑 GNFS。照穩紮穩打的邏輯,下一步該挑一個 230 位數等級難度的數字,一步一步把剩下的兩個數量級跨過去。但他自己的估計是 RSA-260 在一個月內做得完,所以直接跳過中間那一步、開始跑多項式選擇——即使他當時很清楚,線性代數那一段還遠遠沒優化好。合理的推測是,後來那 643 個 GPU-day 燒在多項式選擇上,某種程度是這個賭注留下的尾款——但文章沒有把兩件事明講在一起。這裡可以合理猜測:他敢在多項式選擇都還沒跑完的時候就喊出「一個月」,底氣多半來自那十年的興趣經驗,而不是臨場亂猜——C311 就是最近一次的參考點。

GNFS 怎麼跑:篩出關係、解出矩陣

GNFS(general number field sieve)不是新演算法——這是目前已知,對大多數 100 位數以上的數字來說最有效率的演算法,先前打破紀錄的 RSA 數字分解,用的都是它。整條管線分三段序列執行,一段做完才能進下一段:多項式選擇、格篩(lattice sieving)、線性系統求解。這裡順帶說明一下位數換算:RSA-260 的「260」指十進位位數,換算成位元大約是 862 bits;RSA-1024 則是以位元數命名,換算成十進位是 309 位數——這也是為什麼後面 Eric Lu 會說 RSA-1024 只比 RSA-260 多需要 78 倍算力,而不是聽起來更誇張的等級。

第一段多項式選擇的工作是「fixes the number field over which the algorithm is run」——替待分解的數挑一個數體,Eric Lu 說「多項式選得好,能在格篩那一步拿到一個常數倍的加速」。這段理論上輕量,這次卻實際燒了 643 個 GPU-day,Eric Lu 自己在文章裡承認,這個數字「異常地高,基本上是操作者能力不足造成的」。

第二段格篩才是整條管線裡最貴的一段:目標是在 GF(2) 上「produce lots (8.3 billion in our case) of sparse linear relations」——這次一共篩出 83 億條稀疏線性關係。這段吃掉 3,813 個 GPU-day,佔總成本近八成。多項式選擇其實也被搬上了 GPU(團隊叫它 gps1,借用了 msieve 已經調校好的實作)——接下來整篇文章要花最多篇幅講的,是吃掉時間最多的格篩。

格篩之所以難搬上 GPU,卡的是記憶體存取的型態。篩選以「special q」為單位,天生可以平行到「令人尷尬」的程度——每個 special q 彼此獨立,理論上丟給多少顆 GPU 都吃得下。麻煩出在每個工作項目內部:要在一個大陣列裡做大量讀寫,而且落點「(就我們的目的而言)是偽隨機的」。GPU 最擅長的是規律、可預期的存取型態,最怕的正是這種到處亂跳的隨機讀寫;Eric Lu 自己的結論很直接:「處理這個問題,是優化篩選時最主要的技術挑戰」。這也解釋了 gslin 那句好奇——不是沒人想過把格篩搬上 GPU,是「所有先前公開的 GNFS 分解紀錄,格篩都只用 CPU 做;老實說,因為要在 GPU 上有效率地實作格篩本身就有一堆難題,長期以來根本不確定 GPU 格篩到底划不划算」。這句話點出這次工程的價值:做出來,而且做得划算。

第三段線性系統求解,把篩出來的關係「pack...into a large matrix over GF(2)」,解出線性相依,找出能拆出質因數的那組解。這個規模的線性代數通常得靠分散式運算,需要吃下大量通訊頻寬——Eric Lu 說這在 Infiniband 和 NVLink 上「多得是」。拿來解的演算法叫 block Wiedemann,他的說法是:「這個演算法能把通訊上的限制放寬一些,而且 CADO-NFS 裡這個演算法的實作本身也還有優化空間、也能跑在 GPU 上——我們就做了。」這段用了 467 個 GPU-day,其中約 7% 因為當機或被更重要的工作搶佔而白跑。三段加起來,Eric Lu 估計總成本是 4,900 個 GPU-day,換算 13.5 個 GPU-year;appendix 裡寫明成本假設是每 CPU core-hour $0.08、每 GPU-hour $3.50,照這個價格折算,大約四十萬美元——比先前公開已知最好的 GNFS 實作便宜十倍。「先前公開已知最好的實作」具體指誰,文章沒有點名——最接近的參照只有 RSA-250 那筆 2020 年的紀錄,但 RSA-250 本身用的是 CPU 格篩,不是 GPU,嚴格說不是同一個擂台上的對照。換句話說,「便宜十倍」這句話,比的可能不是同代 GPU 實作,而是格篩這件事本身,從 CPU 換到 GPU 之後的整體降幅。

點任一階段看細節 · 3 個階段

GNFS 三段管線,錢燒在哪裡

GNFS 三段管線,錢燒在哪裡 多項式選擇 643 GPU-day · 決定數體,這次異常偏高 格篩(glas,GPU 版 las) 3,813 GPU-day · 篩出 83 億條稀疏線性關係,佔近八成成本 glas:las 的 GPU 版替代品 線性系統求解 467 GPU-day · 約 7% 因當機或搶佔白跑

點任一階段看細節

多項式選擇 · 643 GPU-day

「Polynomial selection fixes the number field over which the algorithm is run. The choice of polynomial controls a constant-factor speedup on the lattice sieving step.」——這段挑的多項式會影響下一段格篩能拿到多少加速,這次跑出的天數「異常地高,基本上是操作者能力不足造成的」,Eric Lu 自己這樣寫。

格篩 · 3,813 GPU-day

目標是「produce lots (8.3 billion in our case) of sparse linear relations over GF(2)」——這段吃掉全部成本的近八成,也是整個工程真正要優化的目標:glas 是 las(CADO-NFS 原本的 CPU 版格篩器)搬上 GPU 之後的一比一替代品。

線性系統求解 · 467 GPU-day

「we pack these relations into a large matrix over GF(2) and use linear system solving to find a linear dependence」——找出質因數的最後一步,約 7% 的算力因當機或被更重要的工作搶佔而沒有產生進度。

為什麼是格篩先上 GPU:glas 與 Devin 的自主權

格篩吃掉近八成成本,要省錢,答案很直接:先把這段搬上 GPU。8 月 13 日太平洋時間凌晨 0 點 11 分,Eric Lu 把這個任務交給 Devin——原話是「我把 Devin 對準了做出 siever 那一步的一比一替代品」。底層用的是一套「大幅改寫過的 CADO-NFS」——CADO-NFS 是學界既有的 GNFS 開源實作;多項式選擇這段另外借了 msieve 裡已經調校好的核心。改到什麼程度?按 Eric Lu 自己列的清單,整條 CADO-NFS pipeline 裡沒被動過的程式只剩四個:cado-nfs.py 本身、負責第二階段多項式選擇的 polyselect_ropt、makefb、還有 dup1;連原本只是拿來產生測試資料的 fake_rels,都得重新優化才能在這個規模下跑出堪用的效能。格篩器叫 glas,是 CADO-NFS 原本 CPU 版格篩器 las 的一比一替代品——glas 字面意思就是「GPU 版的 las」。

格篩器最後成形的那個晚上,Eric Lu 自己的描述是:「我去睡了。醒來發現,又經過 7 小時的迭代之後,Devin 成功了。」接下來一週,他把 Devin 推去優化格篩,再優化整條 GNFS pipeline。GPU 叢集操作、cluster 排程這些原本是 Devin 在做 ML 相關工作時累積的技能,被直接拿來用在數論計算這個完全不同的領域上,Eric Lu 對此的評語很簡單:「我對 Devin 在這裡展現的類推能力印象很深刻。」他事後這樣形容自己的角色:「我的角色主要是設優先序、訂 benchmark、抓出工作方向跑偏的訊號,量測、cluster 操作、效能優化這些,Devin 自主端到端處理。」但他也留了一個保留:「我不能說 Devin 是完全自主跑完整條 end-to-end pipeline 的」——「不知為何,答案似乎還是:很多。」按 Devin 事後自己回報,整個分解計畫總共用掉 233 個 session、14,450 個 ACU(Devin 自己的算力計量單位),他親自出手傳訊息的有 192 個,加起來送出 82,702 個字、502,887 個字元、3,328 則訊息。

這整件事的起點,按 Eric Lu 自己的說法,是「過去幾週,Cognition 研究團隊和我一直在優化我們的 job scheduler,好更善用 disaggregated compute」——RSA-260 從頭到尾只是這個優化過程裡順手做出來的副專案,動用的是他自己說的「個位數百分比的 cluster」,而且是「花在閒置或零碎算力上,沒有額外邊際成本」,不是傾全公司之力堆出來的結果。

線性代數那一段原本的規劃更講究:他最初打算用 m = n = 512、兩條寬度 256 的序列,跑在 16 個 GB200 節點、4x4 的 MPI 網格上(每組 64 顆 GPU),而且想用「dedicated cliques」——這個詞的意思,原文沒有進一步說明。最後沒用成,原文是「我原本打算用 dedicated cliques,但因為更高優先序工作的需求做不到,只能照舊用散落的算力」。這剛好印證了前面那句「個位數百分比」:這從頭到尾是插在正職工作縫隙裡的專案,連理想的網路拓樸都得讓路。appendix 裡列出的完整設定更雜——線性代數的網格配置橫跨 4x2、4x4、8x4 到 16x4,機型也在 GB300 跟 GB200 之間換來換去,不是同一套硬體從頭跑到尾。整個過程也不是只有 Devin 跟 Eric Lu 兩者——他在文末特別謝了 Alex Lombardi,感謝對方在數學方面的諮詢與大量校對工作,說明關鍵的數學判斷還是有人在把關。

時間線攤開來,整條 pipeline 跑了不到 16 天:多項式選擇 8 月 18 日 UTC 中午開始,8 月 22 日格篩起跑,8 月 30 日早上篩滿目標,當天下午轉進線性代數,9 月 3 日凌晨兩個質因數出爐。格篩這段——最貴、也是新搬上 GPU 的那段——花了將近 8 天;線性代數只花了 3 天多。appendix 的設定值也留了一點痕跡:格篩每個節點開 22 條平行執行緒(las.threads 22),這個數字是調過的。

最後解出來的兩個質因數,長度剛好對稱——各是 130 位數的質數,原始輸出裡就標著「(p130)」。他的估計沒有落空,還贏了自己的預期一半:當初說「一個月內做得完」,實際上 16 天就解出質因數。攤開在這 16 天的時間軸上,平均一天要跟 Devin 來回 200 多則訊息、開將近 12 個 session——全程都在盯著。

拖曳時間軸看每個階段花了多久 · 5 個節點

拖曳圓點,或直接看下面五個節點的時間與說明。

帳單怎麼往上長——RSA-1024 與 RSA-2048

這條成本曲線往上怎麼長,比四十萬美元本身更值得看。Eric Lu 給了一個換算基準:RSA-1024 寫成十進位是 309 位數,用同一套標準 GNFS scaling law 外插,只比 RSA-260 多需要 78 倍算力——不是天文數字。照這個倍數,他估計用市價 GPU 拆開 RSA-1024,大約要三千萬美元。他同時給了一個誠實的保留:「我很清楚目前這套實作還遠遠不是最優,如果再花一些力氣優化,把成本再砍一半我不會意外。」

拖曳位數與 GPU 價格看成本怎麼變 · 兩個滑桿

260
3.50
RSA 位數(decimal digits) 估計成本(美元,log scale) 260(RSA-260,作者估算) 309(RSA-1024,外插)
兩端點是來源給的數字:RSA-260 是作者事後估算的約 4,900 GPU-day;RSA-1024 用「標準 GNFS scaling 只比 RSA-260 多 78 倍算力」這句話外插。中間的曲線形狀套用 GNFS 的標準次指數複雜度公式,不是額外量出來的數字。

這條曲線的兩端都是來源給的數字,中間是套 GNFS 標準次指數公式內插出來的——在預設的 $3.50/GPU-hour 下,滑到 309 位數這端,算出來的答案落在三千兩百萬美元上下,跟 Eric Lu 自己另外估的三千萬美元很接近。同一個「78 倍算力」的門檻,換算成美元會隨 GPU 市場價格浮動——這正是右邊那個價格滑桿想讓你看到的。

把賽前的猜測跟事後的實測擺在一起看,落差說明了問題出在哪裡:

數字 量 單位 誰給的 · 何時
RSA-250 實際紀錄(2020)2,700core-yeargslin 引用的已知歷史數字
RSA-260 賽前粗估3,400-4,100core-yeargslin,9/8,標準 scaling law
RSA-260 賽前估算(GPU 加速後)25GPU-yeargslin,9/8,社群共識
RSA-260 實際結果13.5GPU-year($400k)Cognition,8/18-9/3 事後公布
RSA-1024 賽前粗估2,000GPU-yeargslin,9/8,社群共識
RSA-1024 事後外插30,000,000美元Cognition,用 78x scaling 換算
最樂觀的賽前估算是 25 GPU-year,Cognition 實測交出的答案是 13.5 GPU-year——連社群裡最積極的猜測都還是高估了將近一倍。

最樂觀的賽前猜測是 25 GPU-year,Cognition 交出的實際答案是 13.5 GPU-year——連社群裡最積極的估算都還是高了將近一倍。這個落差不是 scaling law 算錯了,是 scaling law 本來就沒辦法預測「把格篩搬上 GPU 這件事,工程實作能榨出多少額外空間」;那個空間,這次是靠 Devin 用 192 個 session、十幾天磨出來的。

另一頭,RSA-2048 沒有變得比較不安全。Eric Lu 的原話:「RSA-2048 依然比 RSA-1024 難上大約十億倍,看起來沒有被這次工作實質影響。」十億倍不是修辭,是這次工程進展完全追不上的量級差距——就算 GPU 版 GNFS 再優化十倍、一百倍,RSA-2048 短期內都輪不到。這個數量級不是巧合:GNFS 的複雜度隨數字長度呈次指數成長,從 309 位數翻倍到 617 位數,計算量沿著這種次指數曲線往上跳,遠遠超過兩倍——十億倍這個數字,本質上跟前面那條成本曲線是同一套數學,只是端點換成了 RSA-2048。

該緊張的,是還留著 1024-bit RSA key 的系統。這個位元數早在 2013 年就被正式列為淘汰——不是因為它突然變得容易拆,是因為它本來就已經不夠。Eric Lu 在文章裡直接寫了這句話當背景:「state-of-the-art RSA public keys contain 2048 bit (~617 digit) factoring problems, while 1024-bit (~309 digit) RSA was deprecated in 2013」。RSA-260 這次進展,給舊警訊訂出一個新價碼:三千萬美元買得到答案,而且這個價碼只會繼續往下掉。他在結論前留了一句態度很明確的話:「我認為我們不該迴避這類探索。」特別是「如果一個問題可以靠『寫程式解決』,看起來就值得立刻動手試試看」——RSA-260 這次示範的,某種程度上正是這句話的實作。他自己在結論裡的說法是:「密碼分析這類工作、乃至更廣義的計算數學,甚至多數大規模科學計算研究,門檻都比過去低得多了。」

合理的推測是,一套系統裡如果還留著 1024-bit RSA key,多半是某個舊憑證、舊 handshake 相容性設定、或者某條沒人記得要更新的設定檔,被一路留到現在。這篇文章沒有告訴你怎麼找出這些角落——但它把「找出來、換掉」這件事的優先序,往上調了一格:三千萬美元不是抽象的威脅模型,是一個已經有人算過、而且還在往下降的具體價碼。

So what:如果你手上的系統還留著 1024-bit RSA key,問題不是「現在會不會被算出來」——三千萬美元對一個國家級對手從來不是門檻;問題是「為什麼 2013 年就該換的東西,到現在還沒換」。