ベンチマークポカリプス
原文は Dan Luu により に公開されました。 このブログを購読する
最近、vulnpocalypse(脆弱性の黙示録)について盛んに語られているが、自分はセキュリティの専門家ではないので付け加えることはあまりない。ただ、それと密接に関連しつつも(公平を期して言えば、深刻さでは劣るが)あまり議論されていない問題、すなわちベンチマークポカリプスについては、ほとんど語られていないように思う。
かつてないほど本当の性能向上を実現しやすくなった一方で、ベンチマークを報酬ハッキングして見かけだけの性能向上をでっち上げるのも、かつてないほど容易になっている。前者は多くの企業で静かに起きているのだろうが、後者は今や少なくとも週に一度は目にする。誰かが「Xを最適化して既存ソフトウェアより大幅に高速化した」と主張するが、よく見てみると、実際にやったのは現実のワークロードでは性能が上がらないのにベンチマーク上のスコアだけが上がるような最適化だった、というケースだ。こうした事例は「XをRustで書き直しました」系のプロジェクト1や、資金調達や販売を狙う新しいスタートアップに多いが、他の種類のプロジェクトでも起きている。
もちろん、自分の推しプロジェクトがいかに優れているかを示すために、代表性のないマイクロベンチマークを振りかざす人は昔からいた。代表性のないマイクロベンチマークをでっち上げるのは昔から簡単で、今後もそれは変わらないだろう。変わったのは、大規模なベンチマークスイートをハックするのに以前は多大な労力がかかったのに対し、今ではLLMをループで回すだけでできてしまうという点だ。こうしたことがまだ困難だった時代にも、大規模ベンチマークをハックした有名な事例は少なくない。例えば、SPECint / SPECfpがワークステーション性能の指標として重視されていた遠い昔、CPUベンダーはベンチマーク内の計算を高速化するコンパイラの「最適化」を見つけようと躍起になっていた。SunがSPECfp2000の179.artを12倍高速化する方法を見つけたのもその一例だ。熟練したエンジニアがそうしたベンチマークハックを見つけるために多くの時間を費やしていた。LLMはこれを自明なものにするだけでなく、デフォルトでやってのける。その結果、かつては信頼できたベンチマークも、結果を監査するか、監査した誰かを信頼しない限り、意味をなさなくなっている。
他人の杜撰な主張をあげつらう代わりに、自分がエージェントに作らせた正規表現エンジンであるFREを例に挙げよう。かなり包括的なrebar正規表現ベンチマークスイートでRustのregexクレートを上回っているのだから、「世界最速の正規表現エンジンだ」と主張することもできる。ただし、これはエージェントを約1か月ループで回し、「ベンチマークに過適合するな」と指示はしたものの、実質的な監督はせずに作らせたものだ。概して、LLMにベンチマークで良いスコアを出させるのはかなり簡単で、今回も例外ではなかった。Rustのregexクレートと同等の性能に追いつくのに2週間ほど、さらにrebarで1.4倍高速にするのに2週間ほどかかった2。だが、エージェントはそれを防ぐための厳重なガードレールを設けなければ、報酬ハッキングや過適合をしがちだ。今回は実験として、あえてそうした対策をしなかった。
過適合をチェックするために、やや恣意的ではあるが3ripgrepのベンチマークコーパスをホールドアウトとして使ってみた。すると、アルゴリズム的な爆発でベンチマークがいつまでも終わらないケースを除いても10倍遅く、そもそも完了を待つのが現実的でないほど時間がかかるケースすらあった。40%高速どころではない。
Andrew Gallant(別名BurntSushi)のrebarベンチマークスイートは、ベンチマークスイートとしてはかなり包括的な部類に入るが、それでもエージェントは必ずしも汎用的な性能向上につながらない形で過適合しながら高得点を取ることに何の問題もない。
次に試したのは、以前話したトリックだ。LLMに単に「ズルするな」と伝えるのではなく、「判定に使われるホールドアウトのベンチマークセットがある」と伝える方法である。その結果、LLMは性能をある程度汎化させ、ホールドアウトでは全体で約2.4倍遅い程度まで改善した。現存する最速の汎用正規表現エンジンと比較していることを考えれば、かなり良いように聞こえる。しかし、これらのベンチマークはコーディングエージェントが作ったものだということを思い出してほしい。何を測っているのかをよく見ると、少なくとも同じ重みで含めるのが明らかに不適切なものもいくつかある。本当に重要と思われるベンチマークだけに絞ると、FREはホールドアウトで4倍遅い0。昔ながらの「ホールドアウトがあると伝えろ」トリックを適用する前よりは大幅に改善したが、それでも40%高速とは程遠い。
この件で興味深いと思った点がいくつかある:
- エージェントにベンチマークで勝つために報酬ハッキングや過適合をするなと指示しても、非自明なベンチマークで無意味な形で「勝利」するのは簡単だということ
- 今回も、LLMに汎化させろ、過適合するな、ズルするなと伝えるよりも、ホールドアウトセットがあると伝える方がうまくいったこと
- FREの全体的な性能はそれほど良くないものの、一部のユースケースでは実際に優れていること。概して、かつては高度なエンジニアリング経験を要した特定用途向けの特化コードを書くコストが大幅に下がったこと
(1)について、怪しい主張をあれほど頻繁に見かけるのも当然だ。以前であれば、40%高速だと嘘の主張ができるほど巧みに性能を偽装するFREのようなものを作るには、かなりの専門知識が必要だった。最低限、文字列照合アルゴリズムや正規表現エンジンについてかなり深い理解に加え、一般的なコード最適化やSIMD最適化の確かなスキルが求められた。FREには正規表現を機械語にコンパイルするモードもあるので、コンパイラの専門知識も必要になる。今では、(ズルを望むかどうかにかかわらず)数分のタイピングでそうしたベンチマークのごまかしが手に入る。
(2)については、これが一般化できるのかどうか興味はあるが、判断できるほど十分な事例はまだ試していない。
(3)について、ほとんど人手がかかっていないバイブコーディングされた正規表現ライブラリで、堅牢で既存の十分にテストされたライブラリより遅いものをわざわざ使う理由はないので、成果物としてのFRE自体には面白みを感じない。ここで興味深いのは、かつては希少で専門的かつ高価だった知識を、LLMがどれだけ代替できるようになったかという点だ。
昔であれば、知識があったとしても、自分のワークロードに最適化されたカスタムの正規表現エンジンをわざわざ書くことはまずなかっただろう。そのレベルのカスタマイズをする大規模なユースケースも一部にはあった。例えば、私がBingのインデックスに携わっていたとき、コードベースには複数の異なるコンパイラが含まれていた。極限まで性能を絞り出そうとした担当者がいたためだ。検索エンジンではコンパイル時間とコンパイル後の実行性能の両方が重要で、場所によってトレードオフが異なるため、通常のプロジェクトならインタプリタを使ったり「普通のコード」でデータ構造を直接辿ったりするところに、それぞれ専用のコンパイラを書くことでより良い性能が得られる。そうしたコンパイラを書いた人物なら、正規表現のようなコードに取り組む際にも複数のカスタム正規表現エンジンを書いたかもしれないが、その両方の専門知識と意欲を持ち、ましてや仕事でそうした特化コードにそれだけの時間を費やす自由を持つ人はごくわずかだ。そのBingのエンジニア(当時はPartnerレベルのエンジニアで、検索インデックスでの仕事によりDistinguished Engineerに昇進した)のコストと、LLMをループで回すコストを比べれば、この種の特化コードを書くコストは何桁も下がったことになる。
今でもAIはまやかしだと思っている人は、この投稿の前半を読んで「やはりAIは偽物を作るから、偽物の正規表現エンジンができたのだ」と思うかもしれない。しかし結果を見れば、ホールドアウトで世界最速の正規表現エンジンの半分より少し遅い程度でありながら、多くの実際のワークロードでは本当に高速であり(過適合の大部分は特定のベンチマークパターンを特別扱いしたというより、ある大まかな形状のものには最適化が効き、別の形状のものには効かないという類のものだ)、決して偽物の正規表現エンジンとは程遠い。実際、コンパイル時間を無視して繰り返し検索や非常に長い検索を行う場合(これは多くの実際のユースケースで理にかなったことだ)、ネイティブコードにコンパイルするモードではホールドアウトでRustのregexクレートを実際に上回る。FREでの自分の目標が、数分の人手で作れるものを何でも作ることではなく、高速な正規表現エンジンを作ることだったなら、幅広いホールドアウトベンチマークでかなり競争力があったはずだと思う(多様な本番ワークロードで試して初めて見つかるような欠落はあるにせよ)。そして、この急ごしらえのバージョンでさえ、一部の実際のワークロードでは非常に優れている。
つまり、FREという正規表現エンジン全体ではRustのregexクレートより性能が劣るものの、ワークロードやユースケースに特化することで得られる利得を考えれば、場合によっては自分専用の特化した正規表現エンジンをどこかに組み込むことも合理的になりうるし、これは他の様々な低レベルソフトウェアについても同様だ。AI至上主義者でなくても、数年以内にデータベースのようなより大きなものについても同様のことが起きるのは十分にあり得ると考えるのはもっともだ。
Yossi Kreinin、Jamie Brandon、Peter Geoghegan、Luke Burton、John Spurling、Dennis Snell、Max Bittkerの各氏に、コメント/修正/議論について感謝する。
追記:ここでの議論の通り、LLMによって何かをちょっとつついて好奇心を満たすのにかかる時間は大幅に減った一方で、それを書き上げてブログに載せられるほど厳密にするのにかかる時間はほとんど変わっていない(様々な理由で、むしろ増えていると思う)。その結果、これまで以上に多くの分析をしているが、少数の友人と共有するだけで公開はしていない。実験として、今回はかなり駆け足で書き上げてみることにした。普段ブログに載せるものと比べて、仕上げや厳密さの基準を大幅に下げ、ブログ記事というより友人とのカジュアルな会話で話すような調子で書いている。この投稿の目標は30分ほどで書き上げることだったので、昼休みに済ませられる程度で、あまり時間をかけずにできるものだ。これについて意見があれば、ぜひ聞かせてほしい。
もちろん、ここでの注意点として、すべての数値は普段より間違っているリスクが高い。あるベンチマークを1、2分見ただけで問題を1つ見つけ、別のベンチマークを1分見ただけでまた別の問題を見つけた。両方とも修正済みだが、これは他にも追いきれていない問題があることを示唆している。ただ、ベンチマークの数値が間違っているという点では、これは非常に現実的だ!ベンチマークの数値を詳しく調べるたびに、例えばここやここのように、数値は間違っている。ベンチマークポカリプスのもう一つの側面は、少なくとも今のところ、LLMは杜撰なベンチマークを行うのが得意だということだ。だから、たとえ本当の性能向上があったとしても、ベンチマーク設定が妥当であることを確認するために相当な注意が払われていない限り、LLMが生成したベンチマーク設定からはそれを判断できないのが普通だ。
付録:FREベンチマークの詳細
上記を書いてから公開するまでの間に見つかったことだが、FREがrebarでRustのregexクレートより40%高速だというLLMの主張も、間違っていた。あるいは、間違ってはいないにしても、少なくともミスリーディングだった。実際にはrebarのベンチマークと同じ方法でベンチマークを実行していなかったのだ。ベンチマーク結果を1分ほどチェックして2つの問題を見つけた後にこれを確認したのだが、https://github.com/BurntSushi/rebarにある通りにrebarのベンチマークを実行するよう指示していたにもかかわらず、LLMはFREが性能を向上させるための最適化を行えるようにインターフェースを変更していた。それを修正したところ、rebarでFREがRustより1.4倍高速だったはずが、1.5倍遅い(そしてre2よりは「わずか」2倍速い)という結果になった。つまり当初の結果は二重にフェイクだった。FREがrebarベンチマークに高度に過適合していただけでなく、結果自体にもズルが含まれていたのだ。
しかし良い面もある。これはFREのrebarでの性能(Rustより1.5倍遅い)とホールドアウトベンチマークでの性能(2.4倍遅い)の差が、以前に見えたほど大きくはないことを意味する。つまり「LLMにホールドアウトがあると伝える」トリックは、以前に見えたよりもさらにうまく機能していたことになる。
その後、LLMに数時間ヒルクライムさせたところ、FREは1.28倍高速になったと主張してきた。わずか数時間のLLM実行でこれだけ改善するのは素晴らしいように聞こえるが、さらに1分かけてズルの有無を調べてみると、複数の問題が見つかった。その一つは、(?s)^(.*)$のマッチ数を数える検索で、haystack(データ)を見ることすらなくカウントを返していたケースだ。別のズルのケースは、ベンチマークでは行ごとに実行すべき複数行grepをまとめて行っていたものだった。エージェントを厳格なガードレールなしで1か月ループで回せば、こうしたことが起きるのは驚くことではない。これがここでの主張を強めるのか、それとも弱めるのかは判然としないが、こうした問題をさらに修正したところ、FREは再び1.4倍遅いという結果に戻った。エージェントを一晩回した後、FREは再び1.5倍高速になったと主張してきた。
ここでの当初の目的は、現在の(公開されている)SOTAエージェント(GPT-5.6 Sol)を、非自明なコード最適化問題に対してほとんど監督なしでループで回すと何が起きるかを見ることだったので、ベンチマークをより公平にするためにさらに時間をかけて修正するのではなく、ここで区切り、結果のプロットをいくつか載せておくことにする。
全体として、RustやRE2に対するFREは、rebarベンチマークでは上回る傾向がある(そして上述の通り、その多くは過適合によるものだ)が、すべてのケースでそうなるわけではない(以下のグラフは投稿中で触れた数値と必ずしも一致しない。エージェントが常に変更を加えているため、どのスナップショットもすぐに古くなる一時的な推定値だからだ):
特定のベンチマークや特定のクラスのrebarベンチマークでの性能に興味がある場合は、以下の表を参照してほしい(1より大きい比率はFREの方が高速、1より小さい比率はFREの方が低速であることを意味する):
正規表現を事前にネイティブコードにコンパイルする、コンパイルに非常に時間がかかるAOTコンパイラモードもある。すべての機能がAOTに対応しているわけではないが、対応しているケースでの結果は以下の通りだ。見ての通り、AOTコンパイラは非常に遅く(コンパイル時間のベンチマークでは大敗する)、コンパイルにかなりの時間をかけているにもかかわらず、結果は標準のFRE正規表現エンジンより遅いことも多い(もっとも、多くのケースで高速でもある)。
そしてホールドアウトベンチマークもある。上述の通り、非AOTのFREコードでは、ホールドアウトでの性能はrebarほど良くない。また上述の通り、これはripgrepのようなワークロードを想定したものであることを考えると、「ホットサーチ」のベンチマーク群の方が他よりもおそらく重要であり、その意味でFREの結果は全体のスコアが見せかけているよりも悪い。
ここで注意すべき点の一つは、ホールドアウトのベンチマークケースのうち、コンパイル時間をベンチマークに含めずに繰り返し検索を実行するケースでは、AOTのFREがベンチマークで上回っていることだ。多くのユースケースではコンパイルに数秒かかる正規表現は望ましくないが、そうしたコストが許容されるケースも十分にある。例えばripgrepやSilver Searcherのようなものであれば、すぐにマッチングを開始できる正規表現で実行を開始しつつ、別スレッドでコンパイルを行い、コンパイルが終わり次第より高速なマッチャーに切り替えるといったことが考えられる。自分のCPUが長時間のripgrep検索にどれだけ費やされているかを考えると、そうした戦略は自分自身の作業の性能を改善しうるように思える。LLM以前は、最適化を行う正規表現コンパイラを書く努力に見合うことはおそらくなかったが、今では数トークンで実現可能だ。
ここで注意すべきもう一つの点は、この比較はARM Gravitonマシン上でSVE/SVE2を使って実行されたものであり、FREにはSVE/SVE2最適化が入っているため、ある意味で不公平だということだ。LLM以前は、あらゆるSIMD命令の組み合わせごとに最適化された正規表現を用意する価値はなかったかもしれないが、LLMを使えばそこそこのSIMD最適化をかなり簡単に生成できる。LLMが生成したSIMDコードは人間の専門家に及ばないと感じている知人もいる。例えばJay Stellyは、LLMにSIMDコードを生成させた最後の試みでは、自分の望む品質に到達するのに20回以上のイテレーションがかかったと言っていた。しかし一方で、LLMは人間が一定時間内に試せる数をはるかに超える数の最適化を試せるので、個々の最適化が人間の専門家ほど優れていなくても、全体としては依然としてかなり良い性能を発揮しうる。
この投稿で議論した過適合の問題もある。文脈によっては、その問題は非常に簡単に解決できる場合から、少し解決が難しい場合まである。ここでは何が起きるかを見るために、あえてあまり真剣に問題解決に取り組まなかったが、このAzul AIに取り組んだ際には(あくまで一例だが)それほど大きな労力をかけずに問題を解決できた。ただ、こうした大々的なベンチマークの主張の多くは、人々が過適合を避けるためにほとんど、あるいはまったく努力を払わない、時にはむしろマイナスの努力しか払わないときになされる。LLM以前の時代でも、人々は自分の推しプロジェクトがいかに素晴らしいかを示すために、極めて代表性のないマイクロベンチマークを選ぶことがよくあったが、これは少なくとも非意識的なレベルでは、ベンチマークへの過適合を避けるためのマイナスの努力を伴う。人間の性質を考えれば、人々がミスリーディングな主張をするのをやめるとは思えず、しかもミスリーディングな主張をすることがかつてないほど容易になっているのだから、そうした主張が増えるのは当然だ。
なお、この投稿ではAI以外のソフトウェアについて論じてきたが、ここで述べたことはAIソフトウェアについては二倍当てはまる。例えば、Kimi K3はFable(5)レベルだというコメントをたくさん見かける。しかし、私の知る限り実際に使った人は皆、GPT-5.6 SolやFableよりかなり劣ると感じている。印象的なエンジニアリング成果ではないと言っているわけではないが、ベンチマークで見せる性能ほど、幅広い現実のタスクでの性能は高くないのだ。これは様々なeval的な問題についても当てはまる。例えば、ある友人がICFP 2026コンテストの問題で異なるコーディングエージェントを試したときにもそうだった。セキュリティ問題についても同様で、これはAIラボが間違いなくevalに入れているはずのものだ。例えば、同僚がKimi K3を使って我々のソフトウェアの脆弱性をスキャンさせたところ、GPT-5.6 Solが見つけた脆弱性の約4分の1しか見つからず、GPT-5.6 Solが見つけられなかった脆弱性は一つも見つからず、コスト以外のいかなる面でも優位性はなかった。実際のセキュリティ問題を見つけるために安価なモデルを使っている知人たちが使っているのは、ベンチマークでは性能が劣るが実際にはより良く機能するGLM-5.2のような他のモデルだ。
FREの話題に戻ると、もう一つ付け加えておきたいのは、ホールドアウトベンチマークはエージェントが不明な理由で選んだripgrepベンチマーク設定の任意のサブセットだということだ。エージェントにベンチマークスイート全体を取得するよう頼んだが、この投稿の執筆時点ではまだ完了していなかったので、完了した際の結果がどうなるかはまだわからない。
面白いことに、最も懐疑的に見られているプロジェクトの中にも、自分が一定の信頼を置いているものがある。例えば、pgrustをどこかで見かけるたびに、懐疑的なコメントが大量に寄せられる。しかし、何を最適化しているのか詳細を見たわけではないが、Michael Malisがプロジェクトを立ち上げ(今も関わっている)ので、彼らのベンチマークで何か怪しいことをしているとは思わない。以前は目に入ったベンチマークの主張のほとんどをある程度詳しく調べていたが、今ではそうした主張があまりにも多いため、そうする時間がほとんどなく、他に信じるに足る理由がない限り、主張は(たとえ技術的には正しくても)趣旨としては誤りだと基本的に考えるようにしている。もちろん、これは時に間違うこともある(例えば、Michael Malisを知らなければ、pgrustは単なる低品質な「LLMにこれを書き直させてみた」系プロジェクトだと推測していただろう)が、LLMは人間の注意力をDoS攻撃する驚異的な機械なので、他にどうすればよいのかわからない(LLMに性能の主張を分析させてみたこともあるが、その結果は自分で調べた場合の判断と相関はするものの、しばしばかなり間違っている)。
誰かが数秒(あるいは、適切なフレームワークを使えば、実際には自分の時間をまったく使わずに)で生成したものを、人が理解するのに数分から数時間かかるのだ。これは別の投稿で扱うテーマだが、職場でのこの種のことについての経験を人と話していると、この点で規範が貧弱な企業は今日生産性に本当に苦しんでいる。
[return]これはすべてのrebarベンチマークの幾何平均を指している。これはおそらく正しい指標ではない。というのも、各ベンチマークが同じ重要度を持つと暗黙に仮定しているが、おそらくそうではないからだ。SPEC CPUのようなものとは異なり、rebarベンチマークは全体的な性能を表そうとする意味のある要約指標を提供するものとして位置づけられているわけではない(リポジトリ自体が、それは「厳選されたタスク群におけるいくつかの正規表現エンジンの相対的な速度を測る偏ったバロメーター」であると記している)。しかし、有用な要約指標となる数値を得るには、人々が実際に正規表現をどのように使っているかについて多くのことを知っている必要があり、私はそれについてほぼ何も知らない。私の知る限り、SPEC CPUのSPECfpとSPECintのように2つの異なる数値を持つべきなのか、あるいは正規表現の適用方法が多種多様であるために10や100の数値を持つべきなのかもしれない。
[return]最初に調べた正規表現ベンチマークのいくつかはすでに
rebarに取り込まれていたため、ホールドアウトとして使えなかった。そして、前述の通り、現在のSOTA LLMはベンチマークを作るのがあまり得意ではないので、正規表現の性能について十分な知識がなければ、LLMにホールドアウトベンチマークを作らせることも信頼できなかった。文字列照合アルゴリズムや正規表現の性能について自分はほぼ何も知らないので、それも選択肢になかった。BurntSushiはripgrepとそのベンチマークもメンテナンスしており、それらは
[return]rebarにバンドルされるには大きすぎるため、それらをホールドアウトとして使ってみた。
記事をランダムに読む
コメント
ログインしてコメントする