同じ依頼600件を処理して、平均の待ち時間が151.36秒から34.62秒になりました。使った資源は同じです。
差が出る理由は枠の遊びです。まとめて終わる方式では64.0%が遊んでいました。
終わった依頼の枠に、すぐ次を入れます。全員がそろうのを待たない詰め方です。
継続バッチングは、空いた枠に次の依頼をすぐ入れる詰め方です。
そもそも複数をまとめる理由は処理量です。研究も、大規模言語モデルの高い処理量での提供には、十分に多くの依頼をまとめることが必要になるとしています。
問題はまとめ方です。全員そろってから始めて、全員終わるまで待つと、短く終わった依頼の枠が空いたままになります。
難しいのは、出力が何トークンになるか事前に分からないことです。短く終わる依頼も、長く続く依頼も、始める時点では区別できません。
同じ研究も、依頼ごとの記憶領域について巨大であり、動的に増えたり縮んだりすると述べています。長さが動くことが前提の設計になります。
この記事で比べるのは1番目と2番目です。資源は同じで、順番の付け方だけが違います。
次の節の計測では、1トークンあたりの時間を8ミリ秒で固定しています。実際には同時に処理している数によって変わるので、そのままの数字にはなりません。見せているのは、長さがばらつくときに枠が遊ぶという構造です。覚えておく量の話はKVキャッシュの記事で扱います。
the key-value cache (KV cache) memory for each request is huge and grows and shrinks dynamically原文Kwon et al.「Efficient Memory Management for Large Language Model Serving with PagedAttention」 この内容の有効期限2027-02-18
同じ依頼を2通りの詰め方で処理しました。資源は同じままで、待ち時間も処理量も大きく変わります。
継続バッチングで何が変わるのかを、実際に走らせて測りました。用意したのは依頼600件で、同時に処理できる枠は8つです。
出力の長さはばらつかせました。85%は40から200トークン、15%は400から1000トークンです。実際の問い合わせに近い形にしています。
const slots = new Array(SLOTS).fill(0); // 各枠が空く時刻
for (const q of list) {
let k = 0;
for (let j = 1; j < SLOTS; j++) if (slots[j] < slots[k]) k = j;
const start = Math.max(slots[k], q.arrive);
slots[k] = start + q.out * MS_PER_TOKEN;
}
詰め方 平均の待ち時間 p95 最大 全体の所要 1秒あたり まとめて始めて終わる 151.36秒 260.13秒 272.69秒 326.4秒 1.84件 空いた枠から入れる 34.62秒 60.26秒 66.79秒 120.3秒 4.99件
上の表を見てください。平均の待ち時間が151.36秒から34.62秒になりました。4分の1以下です。
詰め方 枠が埋まっていた時間 空いていた割合 まとめて始めて終わる 941.1秒 64.0% 空いた枠から入れる 941.1秒 2.2%
実際に処理していた時間はどちらも941.1秒で同じです。違うのは、その周りで枠がどれだけ遊んでいたかです。
まとめて終わる方式では64.0%が遊んでいました。40トークンで終わった依頼の枠が、1000トークンの依頼が終わるまで空いたままになります。
詰め方 平均の待ち時間 全体の所要 まとめて始めて終わる 19.67秒 91.0秒 空いた枠から入れる 19.38秒 91.0秒
長さをそろえると、全体の所要はどちらも91.0秒になりました。待ち時間もほぼ同じです。
つまり効いていたのは長さのばらつきです。そろっている処理では、詰め方を変えても得るものがありません。
処理していた時間は同じ。違うのは遊んでいた時間。
High throughput serving of large language models (LLMs) requires batching sufficiently many requests原文Kwon et al.「Efficient Memory Management for Large Language Model Serving with PagedAttention」 この内容の有効期限2027-02-18
効くかどうかは出力の長さのばらつきで決まります。そろっているなら、別の場所を改善したほうが早いです。
継続バッチングを入れる前に確かめることがあります。出力の長さがどれだけばらついているかです。
前の節の計測では、長さをそろえた瞬間に差が消えました。全体の所要はどちらも91.0秒です。
自分の用途で長さがそろっているなら、詰め方を変えても得るものがありません。要約や分類のように、出力が短く一定な処理がこれにあたります。
枠が遊ぶと、そのぶんの記憶領域も遊びます。研究もこの記憶領域は、断片化と重複によって大きく無駄にされうるとしています。
同じ研究は、記憶領域の使い方を工夫することで同じ水準の待ち時間のまま、処理量を2倍から4倍に改善すると報告しています。
さらに踏み込んだ工夫もあります。同じ研究は依頼のなかでも依頼をまたいでも、記憶領域を柔軟に共有して使用量をさらに減らすとしています。
同じ指示を毎回送っている構成では、その部分は共有できます。詰め方とは別の節約です。
長さがばらつくときだけ、詰め方が効く。
this memory can be significantly wasted by fragmentation and redundant duplication原文Kwon et al.「Efficient Memory Management for Large Language Model Serving with PagedAttention」 この内容の有効期限2027-02-18
同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。
出品の仕組みを見る