Ling-3.0-flashが4GPUで生成2.1倍速に

SGLangチームとAnt GroupのLing Infraチームは8月21日、共同でまとめたチューニングの記録を公開した。4基のBlackwell GPU上でLing-3.0-flashを動かし、同時実行数1における1トークンあたりの出力時間(TPOT)を3.33ミリ秒から1.53ミリ秒へと54%短縮、スループットは毎秒288トークンから606トークンに引き上げた。さらに自社で学習した投機的デコーディング用のドラフトモデルDSparkに切り替えたところ、平均TPOTは0.78ミリ秒まで下がり、スループットは毎秒1120トークンに到達、1ステップあたり平均9.95個のドラフトトークンが受理される結果となった。

Ling-3.0-flashは線形注意機構とMoEを組み合わせたハイブリッドモデルで、42層のうち35層がKDA線形注意機構、7層がMLAによるフルアテンションを採用する。ルーティング対象の専門家(エキスパート)は512個、隠れ層の幅は2560、語彙数は約15.7万、bf16で1枚あたり約63GBの重みを載せる計算になる。テストではテンソル並列で4分割し、精度はbf16とした。

暇を持て余しているのは実はGPU

今回の最適化対象はバッチサイズ1のケースに絞られている。公開されている推論最適化の成果の大半は、高い同時実行数における総スループットの引き上げを狙ったものだ。クラウド事業者の課金体系がそこにあるからである。一方でもっと直接的に体感される負荷がある。それが同時実行数1、つまりモデルをローカルで動かす、コード補完を使う、エージェントが一本の長い処理を順に実行する、といった場面だ。ある瞬間に走っているリクエストは一つだけで、ユーザーは画面に文字が出てくるのをじっと待っている。

同時実行数が下がると、GPUは暇になる。1ステップのデコードで発生する計算量はごくわずかで、GPUは仕事を終えると次の命令を待つだけの状態になる。そしてその命令を出すのはCPU側だ。ホスト側のどこか一箇所でもデバイスメモリの値を読み戻してから次の動作を決める必要があると、パイプライン全体がその同期の完了を待って止まってしまう。

"at batch 1, look for blocking reads of device values on the host path before anything else, because each one converts the entire host loop from hidden work into a GPU bubble."

同時実行数1では、まずホスト側の経路にあるデバイス値のブロッキング読み取りを探せ。その一つ一つが、本来は裏に隠れているはずのホスト側の処理をGPUの空白時間に変えてしまう。

待ちを一つずつ潰す

1つ目のカテゴリはホスト側の手待ちだ。対策として各ステップのGPU同期ポイントを取り除く。KDAアテンションのバックエンドに対して、シーケンス長をCPU側に読み戻す必要がないと宣言し、関連するインデックスを常にデバイスメモリ上に留めておく。これによって、k+1ステップ目の命令は、kステップ目で何個のドラフトトークンが受理されたかがまだ分からない段階で発行できるようになり、ホスト側は結果を待って詰まることがなくなる。

2つ目のカテゴリはGPU側のクリティカルパス上の処理を短縮することだ。プログラマティック依存起動(PDL)を使い、直前のカーネルの出力に依存しない重みのロードを前倒しで発行する。ルーティングとMoEの計算は、以前は2回のカーネル起動に分かれていたものを1回にまとめた。512個という規模のエキスパート数では起動オーバーヘッドだけでも無視できない。ルーターゲートとlm_headの計算精度はfp32からbf16に切り替え、これだけで約10%の性能向上を得ている。投機的デコーディング下でのKDAのループ状態は、段階的に更新し検証が通った後に確定させる方式に変更した。

これらの変更はすべてSGLangにマージ済みだ。メタデータをまとめたグラフキャプチャ、統合されたKDA検証カーネル、ホスト側から直接発行するFlashInferの実行プラン(ブロッキングのデバイスメモリ読み戻しを省く)、そしてドラフト・検証・拡張の3ステップを1つにまとめたスケジューリング順序が含まれる。

人が体感できる時間に換算すると

5000トークンの長い回答で概算してみる。1トークン3.33ミリ秒なら書き終わるまで16.6秒、1.53ミリ秒なら7.7秒、0.78ミリ秒なら3.9秒だ。同じマシン、同じモデル、同じ人が待っているのに、「お茶を淹れて戻ってくる」感覚から「話し終わる前に出力が終わっている」感覚へと変わる。この差はGPUを買い替えて生まれたものではなく、ホスト側の待ちを徹底的に取り除いた結果だ。

DSparkの段における鍵となる数字は平均受理長9.95である。投機的デコーディングは、小さなモデルに先に一連のトークンを予測させ、大きなモデルが一度に検証するという仕組みで、当たった分だけ得をする。受理長が10に近いということは、大きなモデルが1回検証するたびに、通常のデコード10回分近くを消化できることを意味する。この数字はドラフトモデルの学習方法と直結している。DSparkのドラフトモデルは、Ling-3.0-flashの事後学習後の出力分布を蒸留したもので、損失関数には受理長を最適化する項が専用に加えられている。予測の的中率は運ではなく、学習によって作り込まれたものだ。

アップストリームとの協業

この記録には3者の名がクレジットされている。SGLang側のRadixArk、AntのLing Infraチーム、そしてAntのinclusionAIだ。モデルの重みと再現用のコマンドも、DSparkのバリアントを含めて公開されている。

中国産のオープンウェイトモデルがランキング上位に位置すること自体は、もはや珍しくない。珍しいのは推論スタックの層で発言力を持つことだ。今回の最適化はアップストリームのフレームワーク側の対応を待つのではなく、実際のハードウェアコストと実運用の負荷を持ち込んでアップストリームのコードを自ら書き換え、それをマージし返すという形を取った。同じフレームワークでデプロイする下流の利用者にとっては、これらのスイッチを入れさえすればそのまま使え、どのモデルを動かしているかとはあまり関係がない。

参考資料:SGLang公式テックブログ、CocoLoop、Ant inclusionAIの公開モデルカード。ブログが示す再現コマンドとベンチマーク結果に照らして、TPOT・スループット・受理長の3項目はいずれも同時実行数1、4枚構成のテンソル並列、bf16の条件下での測定であることを確認した。