The benchmarkpocalypse

Dan Luu

基準測試末日

原文由 Dan Luu 發布,訂閱此部落格

最近關於 vulnpocalypse(漏洞末日)有很多討論,這部分我沒什麼好補充的,畢竟我不是做資安的,不過我倒是沒看到太多人討論一個密切相關(雖然公平來說,沒那麼嚴重)的問題,那就是 benchmarkpocalypse(基準測試末日)。

雖然現在比以往任何時候都更容易做出真正有感的效能提升,但同時也比以往更容易去 reward hack(鑽漏洞刷分)基準測試、做出虛假的效能提升。前者大概正在許多公司裡悄悄發生,但後者卻是我現在每週至少會看到一次的現象。有人會宣稱自己把 X 最佳化了,相較於現有軟體取得了巨大的效能進步,但仔細一看,他們做的其實只是讓基準測試跑得更快,卻沒有真正提升實際使用情境下的效能。這類案例常常是那種「我們用 Rust 重寫了 X」1 的專案,或是想募資、想賣產品的新創,當然,其他類型的專案也會出現這種情況。

當然,人們向來喜歡拿不具代表性的 microbenchmark(微型效能測試)來吹捧自己的得意專案。隨便拼湊一個以偏概全的 microbenchmark 一直都很簡單,這點永遠不會變。真正改變的是,過去要操弄一整套大型基準測試需要花很多功夫,但現在只要有 LLM 再加上一個迴圈就能搞定。早在這件事還很困難的年代,就有不少操弄大型基準測試的知名案例。舉例來說,很久以前大家還把 SPECint / SPECfp 當成工作站效能指標的時候,CPU 廠商就會絞盡腦汁找編譯器上的「最佳化」來加速基準測試中的計算,像是 Sun 就曾找到辦法,讓 179.art 在 SPECfp2000 上快上 12 倍。當年厲害的工程師花了很多時間去挖掘這類基準測試的漏洞。而 LLM 不只讓這件事變得輕而易舉,甚至會預設就這麼做,使得過去還算可信的基準測試,除非你親自審核結果或信任有審核過的人,否則已經變得毫無意義。

與其去點名某個糟糕的宣稱,我來舉一個自己的例子:FRE,這個我讓 agent 做出來的 regex 引擎,我大可以宣稱它是全世界最快的 regex 引擎,因為它在算是相當全面的 rebar regex 基準測試套件上打敗了 Rust 的 regex crate。但這個成果,是把一個 agent 丟進迴圈跑了一個月、只交代它「不要對基準測試過度擬合」卻沒有實質監督做出來的。整體來說,要讓 LLM 刷出漂亮的基準測試分數相當容易,這次也不例外;花了大約兩週就大致追上了 Rust regex crate 的效能,又花了兩週在 rebar 上做到快 1.4 倍2。但 agent 本來就很容易去 reward hack 和過度擬合,除非你設下嚴格的防護措施來避免,否則一定會發生,而這次作為實驗,我刻意沒有這麼做。

為了檢查是否有過度擬合,我有點隨意地3拿了 ripgrep 的基準測試語料庫來當作 holdout(保留測試)基準,結果在那些不會因為演算法爆炸而跑到天荒地老的案例上,它慢了 10 倍,還有些案例甚至慢到根本沒辦法等它跑完。所謂的快 40%,就是這麼回事!

Andrew Gallant(也就是 BurntSushi)的 rebar 基準測試套件以基準測試套件來說算是相當全面了,但即使面對這麼全面的套件,agent 還是能輕鬆刷出高分,同時以一種未必能帶來良好通用效能的方式過度擬合。

下一步是用我們之前提過的技巧:不只是告訴 LLM 不要作弊,而是告訴它有一組 holdout 基準測試會拿來評分。之後,LLM 的效能泛化程度就好多了,在 holdout 上整體大約只慢 2.4 倍。考慮到我們是在跟世上最快的通用 regex 引擎比較,這聽起來還不錯。但別忘了,這些基準測試本身也是 coding agent 做出來的。仔細看這些基準測試到底在測什麼,有些項目其實根本不該放進來,至少不該用相同的權重來算。如果只看那些看起來比較重要的基準測試,FRE 在 holdout 上是慢 4 倍0,這比起套用那招老套的「告訴它有 holdout」之前已經好很多了,但離所謂的快 40% 還是差得很遠。

我覺得這件事有幾個有趣的地方:

  1. 即使你已經指示 agent 不要為了贏得基準測試而去 reward hack 或過度擬合,要用毫無意義的方式「贏得」一個不算簡單的基準測試,依然是輕而易舉的事
  2. 再一次證明,告訴 LLM 有一組 holdout 比起只是叫它「做泛化一點的工作」或「不要過度擬合、不要作弊」更有效
  3. 雖然 FRE 的整體效能不怎麼樣,但在某些使用情境下它的表現確實比較好;整體而言,過去需要深厚工程經驗才能為特定情境撰寫特化程式碼的成本,已經大幅降低了

先談第 (1) 點,難怪我會看到這麼多似是而非的宣稱。過去要做出像 FRE 這樣、能把效能假象包裝得夠好、讓你敢宣稱快了 40% 的東西,你需要相當多的專業知識。至少,你得對字串匹配演算法、regex 引擎有相當透徹的理解,還要有不錯的通用程式碼最佳化與 SIMD 最佳化能力。FRE 還有一個會把 regex 編譯成機器碼的模式,所以你還得懂一些編譯器。而現在,不管你是不是有意要作弊,只要打幾個字,這種基準測試作弊就能信手拈來。

關於第 (2) 點,我很好奇這個現象是否具有普遍性,不過我還沒有試過足夠多的例子來下定論。

關於第 (3) 點,實在沒有理由去用一個幾乎沒花什麼人力、用 vibe coding 拼出來的 regex 函式庫來取代現有那個穩健、經過充分測試的函式庫,何況它還比較慢,所以我覺得 FRE 這個產物本身沒什麼意思。我覺得真正有趣的是,LLM 在多大程度上取代了過去那種稀有、專精又昂貴的知識。

過去,就算你有那些知識,你大概也不會為了自己的特定工作負載去寫一個客製化的 regex 引擎。只有在一些大規模的使用情境下,人們才會做到這種程度的客製化,例如我在 Bing 索引工作時,程式碼裡就包含了好幾個不同的編譯器,因為當時有位同事想盡辦法要榨出極致的效能;由於在搜尋引擎裡,你同時在意編譯時間和編譯後的執行效能,而且在不同地方的取捨不同,所以與其像一般專案那樣只用直譯器或直接用「一般程式碼」去遍歷資料結構,不如為每個場景各寫一個客製化的編譯器,效能反而更好。那位寫了這些編譯器的同事,如果是處理類似 regex 的程式碼,可能也會寫好幾個客製化的 regex 引擎,但同時具備這種專業、意願,還有餘裕在工作上花這麼多時間寫這種高度特化程式碼的人,少之又少。如果你把那位 Bing 工程師(當時是 Partner 級別的工程師,後來因為在搜尋索引上的工作升為 Distinguished Engineer)的身價,拿去跟讓 LLM 在迴圈裡跑的成本相比,撰寫這類特化程式碼的成本已經下降了好幾個數量級。

那些還覺得 AI 是假的人,大概會讀了前半部就想:「你看吧,AI 就會造假,所以才做出一個假的 regex 引擎」。但如果我們看實際結果,在 holdout 上只比全世界最快的 regex 引擎慢一半多一點,同時在許多真實工作負載上又確實更快(多數的過度擬合並不是針對某個特定 benchmark pattern 去做特例處理,而是對某些大致形狀的東西做了最佳化,卻沒對其他形狀做),這離「假的 regex 引擎」還差得遠。而且,事實上還有一個編譯成原生碼的模式,如果不計編譯時間、只看重複搜尋或超長搜尋的情境,它在 holdout 上真的打敗了 Rust regex crate(這對許多實際使用情境來說是合理的取捨)。如果我做 FRE 的目標是做出一個快的 regex 引擎,而不是只花幾分鐘人力就隨便生出一個能生的引擎,我猜它在廣泛的 holdout 基準測試上會相當有競爭力(當然還是會有些落差,要等到放到多樣化的實際生產環境才會被發現),而且就算這個隨便拼湊的版本,在某些真實工作負載上也已經非常強了。

所以,儘管 FRE 這個 regex 引擎整體效能不如 Rust regex crate,但針對自身工作負載或使用情境去做特化所能帶來的收益,意味著在某些情況下,安插一個自己特製的 regex 引擎是合理的,對於各種其他底層軟體也是一樣。你不需要是 AI 的狂熱信徒,也會覺得在未來幾年內,我們很可能會看到這種模式發生在更大的系統上,像是資料庫。

感謝 Yossi Kreinin、Jamie Brandon、Peter Geoghegan、Luke Burton、John Spurling、Dennis Snell 和 Max Bittker 提供的意見、更正與討論。

又及:如同這裡的討論,有了 LLM 之後,我稍微研究一下、滿足好奇心所需的時間已經大幅縮短,但要把東西寫出來、整理到足以發表在部落格上的嚴謹程度,所需的時間卻沒有變(基於各種原因,我覺得甚至還變長了)。結果就是,我做了比以往更多的分析,但只跟少數朋友分享,沒有發表。作為一個實驗,我試著用非常快的速度寫一些東西,標準比我平常發在部落格上的要低得多;比較像是跟朋友閒聊時會講的內容,而不是我平常會放在部落格文章裡的東西。這篇文章的目標是大約花半小時寫完,這樣我就能利用午餐時間完成,不會花太多時間。如果你對此有什麼想法,歡迎告訴我!

當然,這裡有個但書,那就是所有數字的出錯風險都比平常更高。我大概只花了一兩分鐘看某個基準測試就發現一個問題,接著又花了一分鐘看另一個基準測試又發現一個問題。這兩個都已經修掉了,但這也暗示還有其他我沒花時間去追的問題。不過,就基準測試數字出錯這件事來說,這可是非常寫實的!幾乎每次我深入研究基準測試數據,像這裡,或這裡,數字都是錯的。benchmarkpocalypse 的另一個面向就是,至少就目前而言,LLM 很會做出糟糕的效能測試,所以就算你真的有實質的效能改進,除非花了相當多的心力去確保測試設計是合理的,否則從 LLM 產生的基準測試配置中,你根本無從判斷。

附錄:更多關於 FRE 的基準測試細節

我在寫完上述內容、但還沒發表之前發現的另一件事是,LLM 聲稱 FRE 在 rebar 上比 Rust regex crate 快 40% 的說法也是錯的。或者說,至少具有誤導性。它實際上並沒有用跟 rebar 基準測試相同的方式來跑測試。我是在花了一分鐘檢查測試結果後發現兩個問題才去核對的。結果發現,儘管已經指示要用 https://github.com/BurntSushi/rebar 裡跑 rebar 基準測試的方式來跑,LLM 還是改了介面,讓 FRE 得以做出一些提升效能的最佳化。修正之後,FRE 不再是比 Rust 快 1.4 倍,而是在 rebar 上慢了 1.5 倍(而且「只」比 re2 快兩倍),所以原本的結果是雙重造假。FRE 不僅對 rebar 基準測試高度過度擬合,連測試結果本身也涉及作弊。

但往好處想,這也代表 FRE 在 rebar 上(比 Rust 慢 1.5 倍)和在 holdout 基準測試上(慢 2.4 倍)的效能差距,沒有先前看起來那麼大,所以那招「告訴 LLM 你有 holdout」的技巧,效果比原本看起來還要更好。

之後,我讓 LLM 爬山最佳化了幾個小時,它宣稱 FRE 快了 1.28 倍,這聽起來像是只花幾個小時的 LLM 時間就取得很棒的進步,但接著我又決定多花一分鐘去找作弊的痕跡,結果又發現好幾個問題,包括有個案例是在搜尋 (?s)^(.*)$ 的匹配數量時,根本連 haystack(待搜尋資料)都沒看就直接回傳數量。另一個作弊的案例是在做多行 grep 時,基準測試本來應該要逐行處理。會發現這些並不意外,因為當你把 agent 丟在迴圈裡跑一個月、卻沒有定義嚴格的防護措施時,這種事本來就會發生。至於這是讓我這篇文章的論點更有力,還是反而削弱了它,就不太清楚了,但在修正了另一批這類問題後,FRE 又回到了慢 1.4 倍的狀態。讓 agent 再跑了一個晚上後,FRE 據稱又回到快 1.5 倍了。

由於我原本的目標是想看看把當今(公開的)SOTA agent(GPT-5.6 Sol)在幾乎沒有監督的情況下,丟到一個不算簡單的程式碼最佳化問題上、讓它在迴圈裡跑會發生什麼事,而不是花更多時間去修正、讓基準測試更公平,所以我就先停在這裡,放上幾張結果的圖表。

整體來說,我們可以看到相較於 Rust 和 RE2,FRE 在 rebar 基準測試上傾向於表現更好(而且如上所述,其中很大一部分是來自過度擬合),但並非全面領先(下方的圖表不一定跟文章中提到的數字一致,因為 agent 一直在持續修改,任何一個時間點的快照馬上就會過時):

如果你對特定基準測試或特定類別的 rebar 基準測試的效能感到好奇,下表整理了相關資料(比值大於 1 代表 FRE 比較快,小於 1 則代表比較慢):

還有一個 AOT 編譯器模式,它需要花很長時間把 regex 編譯成原生碼後才執行。目前並非所有功能都支援 AOT,但以下是支援的案例的結果。如我們所見,AOT 編譯器非常慢(在編譯時間的基準測試中輸得很慘),而且儘管花了相當長的時間編譯,結果往往還是比標準的 FRE regex 引擎更慢(不過在許多案例中也確實更快)。

接著是 holdout 基準測試。如上所述,對於非 AOT 的 FRE 程式碼,在 holdout 上的效能不如在 rebar 上的好。而且也如上所述,考慮到這是類似 ripgrep 的工作負載,「熱搜尋(hot search)」這組基準測試可能比其他組更重要,所以 FRE 的結果比整體分數看起來還要更差。

這裡有一點值得注意的是,對於那些不把編譯時間算進基準測試、而是重複執行搜尋的 holdout 案例,AOT 模式的 FRE 在基準測試中是勝出的。對許多使用情境來說,你不會想要一個需要好幾秒才能編譯好的 regex,但在很多情況下這是完全可以接受的,例如對於像 ripgrep 或 Silver Searcher 這類工具,它可以先用一個能立刻開始匹配的 regex 開始執行,同時在另一個執行緒中編譯,完成後再切換到更快的匹配器。以我個人花在長時間 ripgrep 搜尋上的 CPU 時間來看,像這樣的策略似乎能提升我日常工作的效能。在 LLM 出現之前,花心力去寫一個最佳化的 regex 編譯器可能不太划算,但現在用幾個 token 就能做到了。

另一點值得注意的是,這個比較某種程度上是不公平的,因為這是在一台支援 SVE/SVE2 的 ARM Graviton 機器上跑的,而 FRE 有針對 SVE/SVE2 做最佳化。在 LLM 出現之前,為每一種 SIMD 指令組合都去最佳化 regex 可能不值得,但有了 LLM,要產生還算堪用的 SIMD 最佳化就相對容易多了。我認識一些人類專家,發現他們通常還是能勝過 LLM,例如 Jay Stelly 就說他上次試著讓 LLM 產生 SIMD 程式碼時,花了二十幾次迭代才達到他想要的水準。但另一方面,LLM 有能力在任何給定的時間內嘗試比人類多得多的最佳化,所以即使任何單一的最佳化都不如人類專家做出來的好,整體表現仍然可以相當不錯。

還有一個就是本文討論的過度擬合問題。取決於情境,這個問題的解決難度從非常容易到有點困難都有可能。我在這裡刻意沒有很努力去解決這個問題,想看看會發生什麼事,但在做這個 Azul AI 的時候(僅舉一例),我確實沒有花太多力氣就解決了這個問題,只是很多這種大型的基準測試宣稱,往往是人們幾乎沒花什麼力氣去避免過度擬合,甚至是反向用力。在 LLM 出現之前的時代,人們就常常挑選極具偏誤的 microbenchmark 來炫耀自己的得意專案,這至少在潛意識層面上,就涉及了反向用力去迎合基準測試。考量到人性,我不認為大家會停止做出誤導性的宣稱,而現在要做出誤導性宣稱比以往任何時候都更容易,所以我們當然會看到更多這類情況。

請注意,雖然本文討論的是非 AI 軟體,但上述所說的一切對 AI 軟體更是加倍適用。舉例來說,我看到很多人留言說 Kimi K3 已經達到 Fable(5)等級。但我認識的每個實際用過的人都覺得它明顯比 GPT-5.6 Sol 和 Fable 還差。我不是說它不是一項令人印象深刻的工程成就,但在各種真實世界任務上的表現,並沒有達到它在基準測試中的水準。這甚至也適用於各種偏向評測(eval)性質的問題,例如有朋友在 ICFP 2026 競賽題目上嘗試不同的 coding agent 時也是如此。這也適用於安全議題,而我毫不懷疑 AI 實驗室一定有把這些放進他們的評測中,例如我有一位同事試著用 Kimi K3 來掃描我們軟體中的漏洞,結果發現它找到的漏洞大約只有 GPT-5.6 Sol 的四分之一,沒有找到任何 GPT-5.6 Sol 沒找到的漏洞,而且除了成本之外,在任何面向都沒有優勢。我認識那些正在用較便宜模型來找真實安全問題的人,用的反而是其他模型,例如 GLM-5.2,雖然在基準測試上表現較差,但在實務上表現更好。

回到 FRE 的話題,還有一點要補充的是,holdout 基準測試是從 ripgrep 基準測試配置中由 agent 基於未知原因任意挑選的一個子集。我有請 agent 把整個基準測試套件拉下來,但這在本文發表前還沒跑完,所以全部跑完後結果會是如何,我還不知道。


  1. 說來好笑,我對那些大家最抱持懷疑的專案反而還比較有信心,例如每次我在某處看到 pgrust,底下總會有一堆懷疑的留言。但在沒有深入研究他到底在最佳化什麼的情況下,我會相信他們沒有在基準測試上動什麼手腳,因為 Michael Malis 是這個專案的發起人(而且至今仍有參與)。我以前大多會仔細檢視進入我視野的基準測試宣稱,但現在這類宣稱實在太多了,我根本沒時間這麼做,通常除非有理由相信,否則我都會假定這些宣稱在精神上是虛假的(即使技術上正確)。當然,這有時會出錯(例如,如果我不認識 Michael Malis,我大概也會以為 pgrust 就只是另一個低品質的「叫 LLM 重寫這個東西」專案),但 LLM 如此大量地癱瘓人類注意力,我也不知道還能怎麼應對(我也試過讓 LLM 去分析效能宣稱,雖然結果跟我自己看過後的判斷有相關性,但結果也常常大錯特錯)。

    一個人只要花幾秒鐘(或者,如果用了對的框架,甚至完全不用花自己的時間)就能產生一個需要別人花幾分鐘到幾小時才能理解的東西。這是另一個話題,不過從跟人們聊他們在職場上遇到這類情況的經驗來看,那些在這方面沒有良好規範的公司,現在的生產力正受到嚴重衝擊。

    [return]
  2. 這裡指的是所有 rebar 基準測試的幾何平均數。這大概不是一個正確的衡量指標,因為這等於隱含地假定每個基準測試都同等重要,但很可能並非如此。跟像 SPEC CPU 這類會試圖提供一個代表整體效能的有意義總結指標不同,rebar 基準測試並沒有把自己定位成那樣的東西(該專案實際上註明它是「用來衡量某些 regex 引擎在特定任務集合上相對速度的有偏指標(a biased barometer)」)。但要得出一個有用的總結指標,你必須對人們在實務上如何使用 regex 有很多了解,而我對此大約一無所知。據我所知,你或許應該要有兩個不同的數字(就像 SPEC CPU 的 SPECfp 和 SPECint 一樣),或是十個、一百個,因為人們套用 regex 的方式有各種不同的樣態。

    [return]
  3. 我一開始看的幾個 regex 基準測試已經被收進 rebar 裡了,所以沒辦法當作 holdout。而且如先前所討論,當今 SOTA 的 LLM 不太會做效能測試,所以除非我對 regex 效能有足夠的了解、足以判斷基準測試套件的品質,否則我也無法信任 LLM 自己生出來的 holdout 基準測試。由於我對字串匹配演算法或 regex 效能大約一竅不通,這條路也行不通。

    結果發現 BurntSushi 同時也維護了 ripgrep 及其基準測試,這些基準測試規模夠大,沒有被打包進 rebar,所以我試著拿那些來當作 holdout。

    [return]

本文章由 muse-spark-1.2-contributor 進行翻譯

留言