스크립트
00:00:00皆さん、こんにちは。ハーシャル・ジャインと、こちらのタンミシャです。
00:00:21本日は、LLM推論に関する2時間のワークショップへようこそ。
00:00:26このワークショップの目的は、第一原理からこの領域を理解し、
00:00:33さらに深く掘り下げて、業界全体で何が起きているのかを把握することです。
00:00:39私たちの背景について少しお話しますと、私はAudibleのシニアソフトウェアエンジニアで、
00:00:47過去5年間ML/AIデータプラットフォームを構築してきました。また、
00:00:53個人的にLLM推論に関するオープンソースのハンドブックを書いています。
00:00:59そしてタンミシャは、Xi'an's Bank Corporationのシニア定量モデラーで、
00:01:06最近博士号を取得し、エージェント検証や世界モデルに関する研究を積極的に行っています。
00:01:12では、軽く挙手をお願いできますか。LLM推論が初めてという方はどのくらいいますか?
00:01:24はい、ありがとうございます。では、実際にこれらのモデルを本番環境にデプロイし、
00:01:33チューニングや本番トラフィックの処理を行ったことがある方は?分かりました。このワークショップは、
00:01:42初級から中級レベルを対象としています。すべてのスライドと演習はリポジトリに用意されており、
00:01:48まもなく共有します。本日のアジェンダは以下の通りです。まず問題提起から始め、
00:01:56LLM推論に関するいくつかのペインポイントを理解しようと試みます。
00:02:01次に、それらのペインポイントの原因を突き止め、そこから基礎を固めていきます。
00:02:08そして、モデルの最適化とサービングの最適化という2種類の最適化について深く掘り下げます。
00:02:19その後、本番環境にLLM推論ソリューションをデプロイするために利用できる
00:02:25様々なサービングエンジンについて学び、いくつかのベンチマーク結果や、
00:02:32どのエンジンを使用すべきかの判断チャートを紹介します。
00:02:39さて、ペインポイントを理解するためには、まずLLM推論とは何かを知る必要があります。
00:02:47おそらく多くの方はすでにご存知でしょうが、AIに頼むことすべて、
00:02:55例えば動画や音声の生成、テキストの分析、医療レポートや税金の請求書の分析など、
00:03:02これらすべてがLLM推論です。この市場規模は現在約230億ドルにのぼります。
00:03:12Semi-analysisが最近共有したところによると、Googleの検索クエリをLLMでモデル化する場合、360億ドルもの利益の流出が必要になります。
00:03:25そして、検索ビジネスの収益性を維持するためには、クエリコストを0.5セント未満に抑える必要があります。
00:03:33一方で、Business Insiderが報じているように、AIは適切に活用されるべきであり、誰もがトークン使用量の監査と予算管理を開始する必要があります。
00:03:43こうしたことが起きているのはなぜでしょうか?それは、ハードウェアが限られており、計算コストが高く、推論コストが高いためです。
00:03:50そしてAIの利用がますます高まるにつれて、この推論コストはますます上昇しています。
00:04:03この統計はOpenAIの古いものですが、今でも当てはまります。
00:04:11GPT-3のトレーニングコストを見ると、約460万ドルで、これは一度きりのコストでした。
00:04:19しかし、推論コストは継続的なコストです。なぜなら、AI上で開始されるすべてのセッション、すべてのトークン、訪れるすべてのユーザーに応じてスケールする運用コストだからです。
00:04:36これに対抗する方法は基本的に2つしかありません。1つ目は、トークンの使用量を減らすことです。
00:04:47もう1つは、顧客や自社のために、推論サービスプロバイダーとして推論ソリューションの最適化を図ることです。
00:04:58そのため、私たちは次々と登場する新しいソリューションを目の当たりにしています。
00:05:06そこで、今後登場するあらゆるものを理解し評価するのに役立つ基礎を築こうというのが、このアイデアです。
00:05:18では、手始めに、推論に関する様々なペインポイントについての短いデモを行います。
00:05:28これはリポジトリです。
00:05:31ご自身の環境にクローンするか、GitHubで開くこともできます。
00:05:36「LLM Inference at Scale」という名称です。
00:05:39少し背景を説明すると、4ヶ月前、私はLLMの推論について何も知らなかったため、学習を始めました。
00:05:46その際、多くのリソースが散在していることに気づきました。
00:05:49そこで、人々の役に立つように、それらを1箇所にまとめ始めたのです。
00:05:55それでは、実際にこのスライドショーモードを終了して、拡張モードに切り替えます。
00:06:11はい、このリポジトリのREADMEファイルをご覧いただくと、スライドへのリンクがあります。
00:06:27PPTXやベンチマークレポートが格納されているフォルダにつながっています。
00:06:34いつでもダウンロードできます。デモ用として、いくつかのJupyterノートブックを用意しています。
00:06:43Google Colabの代替であるMolabと協力しており、無料のRTX 6000 GPUを提供しています。
00:06:54100GBのRAMを備えたGPUで、簡単に実験できるようにノートブックがすでにセットアップされており、アセットなどもすべて事前設定されています。
00:07:09それでは、簡単なデモAから始めます。
00:07:16ええと、少々お待ちください。
00:07:31推論を行う場合、特定のモデルに対して推論を実行する必要がありますよね?
00:07:40このワークショップでは、シンプルなMistral 7Bモデルを使用しています。
00:07:45サイズが約15GBの小型モデルです。
00:07:49これをGPUにロードします。
00:07:53また、GPUの統計情報もいくつか見ていきます。
00:07:58ご覧の通り、6000 Blackwellで作業を行っています。
00:08:01カンファレンスのWi-Fiを信用していないのでセルを実行していないのではないかと思われるかもしれませんが、
00:08:08以前に実行した結果について説明していきましょう。
00:08:18102GBのGPUを使用しています。
00:08:22ここで最初に思い浮かぶのは、LLM推論を実行したときのメモリ消費量どうなっているかということです。
00:08:31このモデルをロードすると、約15GBを占有していることがわかります。
00:08:37したがって、およそ87.5GBの空きがあります。
00:08:40ここで推論を行うと、入力するデータ量が多いほど、より多くのメモリが必要になることがわかります。
00:08:52増加は緩やかですが、それでも増え続けています。
00:08:564,000、16,000、32,000トークンといったコンテキスト長を扱うと想像してください。
00:09:03このメモリ使用量は非常に大きくなり、アウトオブメモリ(OOM)エラーが発生する可能性があります。
00:09:12ですから、これが最初の問題、つまりトークンの増加に伴ってメモリが増えるという問題です.
00:09:18簡単な視覚化で表すと、このようになります。
00:09:242つ目に気付く問題は、最初のトークンが出力されるまでの時間が非常に遅いということです。
00:09:32これはTTFTと呼ばれる指標で測定します。
00:09:35その略称です。
00:09:37入力サイズに対してTTFTを測定しようとすると、コンテキストが長くなるほどTTFTが遅くなることが分かります。
00:09:52これで2つの問題が挙がりました。
00:09:54トークンサイズに応じてメモリが増加する。
00:09:56トークンサイズに応じてTTFTが増加する。
00:09:59失礼、トークンサイズではなくコンテキストサイズです。
00:10:07そして3つ目はスループットです。
00:10:09スループットとは、1秒あたりに処理できるトークンの数です。
00:10:13そして、1秒あたりに何人のユーザーを処理できるかという問題です。
00:10:16ローカルシステムで非常に単純な実装を行うと、処理は非常にシーケンシャル(順次処理)になります。
00:10:245つのリクエストを送信した場合、それら5つのリクエストは並列ではなく順次処理されます。
00:10:31そのため、複数のユーザーがいる場合、リクエストの完了にかかる時間が長くなってしまいます。
00:10:40これら3つが課題となります。
00:10:434つ目の問題もあります。
00:10:44ここではまだ説明していません。
00:10:45おそらく話が進むにつれてその直感を養っていくことになります。
00:10:48しかし、メモリ、TTFT、スループットの3つが主な問題であると覚えておいてください。
00:10:55了解です。
00:10:56スライドに戻ります。
00:11:02はい。
00:11:03完璧です。
00:11:04これで表示されるはずです。
00:11:17見えていますか?
00:11:18はい。
00:11:19見えています。
00:11:20見えています。
00:11:21はい。
00:11:22見えています。
00:11:23見えています。
00:11:24見えています。
00:11:25はい。
00:11:26見えています。
00:11:27見えています。
00:11:28はい。
00:11:29見えています。
00:11:30はい。
00:11:31見えています。
00:11:32はい。
00:11:33見えています。
00:11:34はい。
00:11:35見えています。
00:11:36見えています。
00:11:37はい。
00:11:38見えています。
00:11:39はい。
00:11:40見えています。
00:11:41はい。
00:11:42見えています。
00:11:43はい。
00:11:44見えています。
00:11:45はい。
00:11:46はい。
00:11:47そのリポジトリ内のworkshopフォルダを開くと、READMEがあり、その中にすべてのリンク、スライド、デモが記載されています。
00:11:55これで大丈夫でしょうか?
00:12:01動いていますか?
00:12:06よし。
00:12:07完璧です。
00:12:09よし。
00:12:10完璧です。
00:12:16よし。
00:12:17それでは基礎の学習に進みましょう。
00:12:19これらのペインポイントの背後にある理由の理解を始めましょう。
00:12:25そのためには、この推論パイプラインを見ていく必要があります。
00:12:32では、入力テキストを取得します。
00:12:35そのテキストには任意の数の単語が含まれます。
00:12:38それらをトークンに変換します。
00:12:41分かりやすくするために、1単語を1トークンと仮定できます。
00:12:46次に、それらを埋め込み表現に変換し、トランスフォーマーに送信します。
00:12:53トランスフォーマーには32層ありますが、それはMistral 7特有のものです。
00:12:58モデルによって層の数が異なります。
00:13:01そして新しいトークンを生成します。
00:13:04そのトークンは基本的に入力に戻されます。
00:13:06さらに別のトークンを生成し、それが続けられます。
00:13:09このパイプライン全体において、計算量の約95%がこれらのトランスフォーマー層によって占められていることがわかります。
00:13:18したがって、トランスフォーマー層の中で何が行われているかを見る価値があります。
00:13:24このトランスフォーマー層の中には、さらにいくつかの層があります。
00:13:28正規化層があります。
00:13:30アテンション層があります。
00:13:32フィードフォワード層などもあります。
00:13:35そして、アテンション層は非常に有名になったものだと思います。
00:13:40「Attention is all you need」の論文です。
00:13:42非常によく知られていると思います。
00:13:44したがって、アテンションは最も計算集約的な層です。
00:13:48そして、そのアテンション層の中で何が行われているかを理解する必要があります。
00:13:53では、アテンションは何をするのでしょうか?
00:13:56入力テキストがある場合、過去のすべてのトークンに対する各トークンのアテンションスコアを見つける必要があります。
00:14:05そのためには、すべてのトークンをキー、クエリ、バリューの空間に射影する必要があります。
00:14:14したがって、より簡単な言葉で言えば、次のように理解してください。
00:14:20例えば10個のトークンがある場合、10個の異なるクエリ、キー、バリューベクトルが必要になります。
00:14:26100個のトークンがある場合は、100個のキーとバリューベクトルが必要になります。
00:14:311000個のトークンがある場合は、1000個のキーとバリューベクトルが必要です。
00:14:35このように、入力サイズを大きくするにつれて、キーとバリューベクトルの数が増加します。
00:14:45そして、Mistral 7BのトークンあたりのKVサイズを計算すると、131 KVになります。
00:14:54これは、KとVという2つのベクトルがあるためです。
00:14:59サイズを掛け合わせる必要があります。
00:15:021つのベクトルは128次元です。
00:15:04それを32個のトランスフォーマー層で掛け合わせる必要があります。
00:15:08さらに、KVヘッドで掛け合わせる必要があります。
00:15:11Mistral 7bの場合、KVヘッドは...
00:15:1532ではありません。異なる種類のアテンションメカニズムを使用しているためです。これについては後ほど確実に説明します。
00:15:23ですが、トークンごとのKVサイズは約131キロバイトになります。
00:15:30では、4Kコンテキストがあると仮定すると、そのサイズは約0.5GBになります。
00:15:3716Kコンテキストにすると、サイズは2.1GBになります。
00:15:42ここでそれをユーザー数で掛け合わせます。
00:15:45複数のユーザーに同時にサービスを提供できると仮定します。
00:15:49GPU内では、4Kコンテキストと80人のユーザーで42GBになる可能性があります。
00:15:58そして、GPUが例えば24GBしかない場合、すでにメモリが不足しています。
00:16:04そのため、それだけのコンテキストを持つ多くのユーザーにサービスを提供することはできません。
00:16:11これを視覚化するために、GPUメモリを見てみましょう。
00:16:14GPUメモリには、かなり固定されたモデル重みがあります。
00:16:19これらは事前トレーニング済みの重みです。
00:16:21同様に固定されたオーバーヘッドもあります。
00:16:24それも変化はしますが、それほど大きくは変わりません。
00:16:29全体として、それは固定されていると見なすことができます。
00:16:32そして、残りのメモリがあります。
00:16:35この残りのメモリは、キーおよびバリューベクトルなどのKVメモリによって使用されます。
00:16:41では、ユーザーが1人いると仮定します。
00:16:46残された80GB全体のメモリに収まるだけの、キーおよびバリューベクトルまたはトークンにしかサービスを提供できません。
00:17:00したがって、簡単なデモでもこれを示すことができます。
00:17:07よし、素晴らしい。
00:17:08よし、素晴らしい。
00:17:08実際に実行できるか確認させてください。
00:17:14よし、素晴らしい。
00:17:15実際に実行できるか確認させてください。
00:17:15一体これはどこだ?
00:17:15よし、素晴らしい。
00:17:16実際に実行できるか確認させてください。
00:17:21一体これはどこだ?
00:17:22よし、素晴らしい。
00:17:23よし、素晴らしい。
00:17:24はい。
00:17:25はい。
00:17:25そのため、実際に実行できるか確認させてください。
00:17:31実際に実行できるか確認させてください。
00:17:33実行できるか確認させてください。
00:17:34実行できるか確認させてください。
00:17:35実行できるか確認させてください。
00:17:36実行できるか確認させてください。
00:17:37よし、素晴らしい。
00:17:38はい。
00:17:39GPUが接続されているのがわかります。
00:17:43よし、素晴らしい。
00:17:44はい。
00:17:45そのため、GPUが接続されているのがわかります。
00:17:56ここでは、構築した数学と直感に基づいて、メモリを確認しようとしています。
00:18:13構築した直感です。
00:18:14モデルメモリは、例えば70億パラメータがあり、16ビット精度で実行している場合、
00:18:1916ビット精度です。
00:18:20合計メモリは14.6GBになります。
00:18:23計算によって基本的にそれを検証できます。
00:18:27したがって、それらの計算をすべて行うと、14.6GBになります。
00:18:33ここでKVとそのサイズの話になります。
00:18:37このKVサイズは、トークンあたり約131 KVです。
00:18:42そして、その計算を行い、視覚化しようとすると...
00:18:47ああ、もちろん。
00:18:52ちょっと待って。
00:18:53わかりました。
00:18:54そしてこれを視覚化してみましょう。
00:19:07よし、素晴らしい。
00:19:10素晴らしい。
00:19:11はい。
00:19:12これがメモリチャートです。
00:19:15ご覧のとおり、コンテキストが増加するにつれて、メモリも増加し続けます。
00:19:21もう一つの認識すべき点は、ユーザーが増えるとメモリも増加するということです。
00:19:28したがって、GPU上で160人のユーザーにサービスを提供したい場合、サポートできるのは...
00:19:37より短いコンテキスト長のみとなります。
00:19:40そのため、サポートできるコンテキスト長と、複数のユーザーや同時ユーザーを1つのGPUに配置することで
00:19:47節約できるコストとの間には、常にトレードオフが存在します。
00:19:54したがって、常にそのトレードオフを考慮する必要があります。
00:19:57これについては、さらにいくつかのスライドで確認していきます。
00:20:06もう一度言っていただけますか?
00:20:10すみません。
00:20:11声が聞こえません。
00:20:12異なるコンテキスト長を持つ異なるプールを確認して、適切なメモリに...
00:20:25サービスを提供できますか?
00:20:26はい。
00:20:27いいね。
00:20:28いいね。
00:20:29わかりました。
00:20:30良いですね。
00:20:31では、話を戻しましょう。
00:20:32それがメモリの話でした。
00:20:33コンテキスト長を増やしたときに、最初のトークン生成までの時間が遅くなった理由を理解する必要があります。
00:20:53コンテキスト長です。
00:20:54そのためには、推論の2つのフェーズを理解する必要があります。
00:20:58そのフェーズとは、プリフィルとデコードのフェーズです。
00:21:01皆さんも多くの記事を目にしていると思いますが、ここではそれを説明したいと思います。
00:21:06大量の入力トークンを送信する場合に行いたいのは、先ほど言及したすべてのトークンのキーおよびバリューベクトルを構築することです。
00:21:20次に、前のトークンに対する各トークンのアテンションスコアを計算します。
00:21:27これら行うすべての操作は、非常にマトリクス(行列)集約的です。
00:21:31非常に計算集約的な操作です。
00:21:34そしてご存じの通り、GPUは高負荷な計算ワークロードに非常によく適しています。
00:21:41そのため、プリフィルは「コンピュートバウンド(計算律速)」と呼ばれます。
00:21:46そして、完了するまでに多少時間がかかります。
00:21:49したがって、このフェーズが完了するのにかかる時間が、最初のトークンまでの時間(TTFT)になります。
00:21:55入力トークンが多い場合、より多くのキーバリューベクトルを生成する必要があります。
00:22:02さらに多くのアテンション計算を行う必要があります。
00:22:05そのため、TTFT(初回トークン生成時間)がますます遅くなります。
00:22:12一方、1つのトークンを生成した後は、別のトークンを生成するためにこれを継続し、順番に1つずつ処理していく必要があります。
00:22:20しかしその過程で、プレフィルと同様に、これまでのすべてのトークンのキーおよびバリューベクトルを毎回構築しなければなりません。
00:22:30あちらでもキーバリューベクトルを構築していたのと同様に、ここでも構築します。
00:22:34しかしデコードフェーズでは、新しいトークンのアテンションの計算のみを行っています。
00:22:40そのため、計算の負担が非常に小さくなっています。
00:22:45そして、メモリバウンドとも呼ばれます。
00:22:48なぜメモリバウンドと呼ばれるのかについては、まもなく見ていきます。
00:22:54したがって、一般的なタイムラインでは、プレフィルとデコードのフェーズはこのように確認できます。
00:22:59つまり、プレフィルにかかる時間が、最初のトークンまでの時間となります。
00:23:03そして、すべてのデコードステップにかかる時間が、基本的にトークン間レイテンシとなります。
00:23:12これが、気にする必要がある4つ目の指標となります。
00:23:18デコードステップにかかっている時間はどれくらいか、という点です。
00:23:21わかりました。
00:23:22了解です。
00:23:23いいですね。
00:23:24それでは、デコードステップやデコードになぜ時間がかかるのでしょうか。
00:23:34そして、なぜメモリバウンド処理と呼ばれるのでしょうか。
00:23:38それについて理解していきましょう。
00:23:40それを理解するために、GPU上での行列計算の仕組みを高レベルで見ていく必要があります。
00:23:47GPUには2種類のメモリがあります。
00:23:50高帯域幅メモリがあります。
00:23:52そして共有メモリがあります。
00:23:55高帯域幅メモリは容量が大きいですが、帯域幅は狭くなっています。
00:24:01帯域幅が低いというのは、低い速度でしかデータを転送できないという意味です。
00:24:06共有メモリと比較すると、共有メモリは容量が小さいですが、非常に高い帯域幅を持っています。
00:24:13つまり、データを非常に高速に出し入れできるということです。
00:24:19したがって、行列計算を行う際には、高帯域幅メモリからチャンク単位でデータを取得する必要があります。
00:24:27そしてそれを共有メモリに配置します。
00:24:30計算を行います。
00:24:32結果を高帯域幅メモリに書き戻します。
00:24:38プレフィルフェーズでは、これを行う必要があるのはこの行列計算を1回だけです。
00:24:46しかしデコードフェーズでは、すべてのトークンを順番に生成していくため、この行列計算を何度も繰り返し行う必要があります。
00:24:59そのため、デコードの速度がどれほど速くても関係ありません。高帯域幅メモリから共有メモリへデータを転送できる速度には限界があるからです。
00:25:14高帯域幅メモリの帯域幅の速度によって制限されるためです。
00:25:18したがって、それがトークンの上限を左右します。つまり、デコードステップから実際にどのくらいの速度でトークンを生成できるかということです。
00:25:32これをルーフラインプロットで確認すると、メモリバウンドと呼ばれる左側のセクションが存在します。
00:25:42数学的には、演算強度によって支配されます。
00:25:47演算強度とは、転送されるデータ1バイトあたりに実行する浮動小数点演算の回数です。
00:25:55したがって、デコードステップでは、これまでのすべてのトークンのキーおよびバリューベクトルやモデルの重みなど、多くのデータを転送するためです。
00:26:08しかし、1つのトークンに対してのみアテンションの計算を行っているため、計算量は少なくなります。
00:26:13そのため、演算強度が非常に低くなります。
00:26:18一方、プレフィルフェーズでは、データの転送は一度だけですが、その後このような重い計算を行います。
00:26:27そのため、演算強度が非常に高くなります。
00:26:30これで、なぜプレフィルの演算強度がデコードと比較して非常に高いのか、数学的な観点からおわかりいただけたかと思います。
00:26:44それでは。
00:26:46これが別の小さなデモになります。
00:26:51わかりました。
00:26:52毎回私がしなければならないことです。
00:26:53わかりました。
00:26:54了解です。
00:26:55素晴らしい。
00:26:56すでに準備できていると良いのですが。
00:26:58そうですね。
00:26:59繰り返しになりますが、モデルを読み込んでいます。
00:27:04さて、これがプレフィルのコストのようなものです。
00:27:09私たちが基本的に行っているのは、入力テキストを取得し、プレフィルステップの処理、つまりそれに要する時間を生成しようと試みることです。
00:27:22入力トークンのサイズを大きくするにつれて、このプレフィルが増加していくことがわかります。
00:27:28おわかりのように、これがTTFTが増加する理由です。
00:27:33そして、デコード時間についてです。
00:27:36デコード時間は、平均してほぼ同じままで推移します。
00:27:41そのため、コールドスタートを無視すると仮定すれば、デコード時間はほぼ平均のラインのあたりになります。
00:27:50それでも入力サイズの影響は受けます。
00:27:57一定の時間というわけではありません。
00:28:00これは、すべての過去のトークンのキーおよびバリューベクトルをメモリから依然として取得する必要があるためです。
00:28:07そのため、デコードステップでは時間にごくわずかな増加が見られます。
00:28:15そしてこれが、典型的なルーフラインプロットになります。
00:28:20わかりました。
00:28:22了解です。
00:28:23プレゼンテーションです。
00:28:24わかりました。
00:28:25了解です。
00:28:26承知いたしました。
00:28:27それでは、スループットの側面について理解していきましょう。
00:28:43実際に何人のユーザーにサービスを提供できるかを把握したいわけです。
00:28:48GPUメモリの図を見たかと思いますが、キーとバリューのベクトルが成長するための空きメモリがあることが確認できました。
00:28:56いいですね。
00:28:57それでは、ユーザーが1人だけであると仮定します。
00:29:01サポートできる合計のKVサイズはどれくらいになるでしょうか。
00:29:09それはコンテキスト長によって定義されます。
00:29:11サポートできる最大ユーザー数は、GPUの可用性、つまりGPUで使用可能なメモリを、ユーザーあたりのキーおよびバリューのサイズで割ったものになります。
00:29:25それを計算すると、同時実行ユーザー数が算出されます。
00:29:32ここで、GPUが固定されており、モデルも固定されていると仮定すると、トークンあたりのKVサイズは固定されます。
00:29:46ここで残っている次元は、コンテキストと同時実行ユーザー数の2つだけです。
00:29:53より多くの同時実行ユーザーにサービスを提供したい場合は、コンテキスト長を短くする必要があります。
00:29:57コンテキスト長を短くすると、品質に影響を与える可能性があります。
00:30:02つまり、これらが現在トレードオフを行っている2つの次元となります。
00:30:09それでは、最大数の同時実行ユーザーに本当にサービスを提供できるでしょうか。
00:30:17理想的な世界では、おそらく不可能です。なぜなら、すべてのビジネスには満たすべきレイテンシのSLAが存在するからです。
00:30:27ですから、デコードステップでお話ししたように、入力が多い場合、デコードにかかる時間はやはり増加します。
00:30:37ユーザー数が多い場合にも増加します。
00:30:40したがって、バッチサイズが大きい場合、最終的にはトークン間レイテンシも影響を受けます。
00:30:51そして、TTFTも影響を受けます。
00:30:53そのため、気にする必要がある3つ目の次元、つまりレイテンシが存在します。
00:30:58したがって、存在する3つの次元とは、品質、レイテンシ、そしてスループットです。
00:31:04結果として、これらの中から選択を迫られるトレードオフの三角形が生じます。
00:31:11プレミアムなチャットアプリケーションの場合、確実に品質を優先したいですし、レイテンシも優先したいはずです。
00:31:21ユーザーに無限に待たせることは望まないでしょうが、より大きなレイテンシについては許容するかもしれません。
00:31:30GPUでサポートできるユーザー数を常に犠牲にし、顧客第一の姿勢をとることでそのコストを負担することができます。
00:31:39例えば、非同期のエージェントワークロードなどを考慮する場合、品質とスループットを間違いなく優先したいでしょう。
00:31:53これらは長時間実行されるタスクだからです。
00:31:56そして、可能な限り多くの同時タスクを処理しつつ、非常に高い品質を維持したいと思うはずです。
00:32:06そして私たちはよく、もしGPUが非常に高価なGPUであれば、自分たちには適していないのではないかと考えがちです。
00:32:19しかし実際には、100万トークンあたりのコストを最も低く抑えて提供できる可能性があります。
00:32:27ただし、必要な最大ユーザー数に関する計算を本当に信用し、そうした見積もりを正確に行う必要があります。
00:32:40そのため、次のように……失礼、素晴らしい。
00:32:55キャパシティカリキュレータについては、使い慣れていたためColabへのリンクがあります。
00:33:01ウィジェットライブラリ全体から移行する必要がありましたが、時間がありませんでした。
00:33:16そのため、面倒くさがってそこでColabを選んでしまいました。
00:33:20研究室の皆さん、申し訳ありません。
00:33:23そのため、VRAMが接続されています。
00:33:34わかりました。
00:33:45ですから、おそらくWi-Fiでしょう。
00:33:46はい、素晴らしい。
00:34:02ここで私たちが何を行ったかというと、VRAM、帯域幅、浮動小数点演算性能、1時間あたりのコストを持ついくつかのGPUを共有しました。
00:34:11そして、このようなシンプルなキャパシティカリキュレータを構築しました。
00:34:19これは単なるKVビジュアライザであり、トークンの数を増やすとKVサイズが増加するのが確認できます。
00:34:29そしてユーザー数を増やすと、サイズがはるかに速いペースで増加します。
00:34:37その後、このキャパシティカリキュレータを実行させます。
00:34:47選択したモデルは、70億パラメータのモデルです。
00:34:56精度をFP16に設定しました。
00:35:01ここで決定することとして、GPUを決定する方法は、まず最も重視する1つの次元を固定する必要があるということです。
00:35:15そのため、プレミアムチャットにおいては、レイテンシが間違いなく重要な要素であると述べました。
00:35:21そして非同期ワークロードについては、単一のGPUから処理したい最小バッチサイズが2つ目の次元となります。
00:35:31したがって、これらを最初に固定する必要があります。
00:35:34それでは、プレミアムチャットアプリケーションを進めていきます。
00:35:39ですので、10ミリ秒のレイテンシで進めることができます。
00:35:44最小バッチサイズは気にしません。
00:35:46つまり、例えば2くらいでも構わないということです。
00:35:53わかりました。
00:35:54したがって、単一のGPU上で約7人の同時実行ユーザーに対応できるでしょう。
00:35:59そして、品質にも焦点を当てたいので、私のコンテキスト制限は非常に重要です。
00:36:07そのため、いくつかのGPUを確認することができます。
00:36:10H-100の80GBは、1時間あたり約8ドルです。
00:36:15しかし、私の300xはどうでしょうか?
00:36:19そうですか?
00:36:20ええ。
00:36:21ですから、1時間あたり約10ドルです。
00:36:24先ほど数式で共有したスループットの計算をすべて行えば、100万トークンあたりのコストを導き出すことができます.
00:36:34それは非常に、非常に低く抑えられる可能性があります.
00:36:37そのため、こうした要素を固定して計算を行い、推論コストを削減するためにGPUを決定する必要があるのです.
00:36:49これが、推論の最適化に向けて踏み出すべき少なくとも最初のステップとなります.
00:36:56わかりました.
00:37:01それでは、次のスライドへ.
00:37:04進みます.
00:37:08はい、素晴らしい.
00:37:10そして次は、モデルの最適化についてです.
00:37:15これで、いくつかの課題やその発生原因、そしてなぜそれが起きていたのかという基礎が築かれました.
00:37:23GPUの容量問題をどのように解決できるかについても見てきました.
00:37:29さらに何ができるのか、何をすべきかを理解する必要があります.
00:37:33それがモデルの最適化であり、ここでタンメイを招きたいと思います.
00:37:39彼は研究時代にこの分野に取り組んできたので、こうしたモデルの最適化について詳しく話してくれるでしょう.
00:37:47はい.
00:37:48了解です.
00:37:49操作を引き継ぎます.
00:37:50引き継ぎますね.
00:37:54はい.
00:37:55こちらで.
00:37:56わかりました.
00:37:57皆さんこんにちは.
00:37:58マイクテスト.
00:37:59やっと声が聞こえていますか?
00:38:00はい.
00:38:01OK.
00:38:02では、こんにちは.
00:38:03タンメイ・シャです.
00:38:04シニア・クオンツ・モデラーとして勤務しつつ、AI研究者としても活動しています.
00:38:08焦点はエージェントの検証であり、現在はワールドモデルを構築しています.
00:38:13それでは本題の、モデルの最適化についてです.
00:38:16モデルの最適化を始める前に、こうした複雑な事柄を理解しやすくするために研究用テンプレートを作成しました.
00:38:25テンプレートはシンプルです.
00:38:28まず、問題を特定します.
00:38:30第2ステップとして、2つのアルゴリズムを使ってその問題を解決します.
00:38:34これらはジョークのアルゴリズムです.
00:38:35まず1つ目は「ダチョウのアルゴリズム」と呼ばれるものです.
00:38:39ダチョウのように、問題に直面したとき、ダチョウは頭を砂に突っ込みます.
00:38:46私たちも全く同じことをします.
00:38:47問題に直面したら、単にそれを無視するのです.
00:38:51これは私たちが従うべき重要なアルゴリズムです.
00:38:552つ目は、新しく作った「ワールドカップ・アルゴリズム」と呼ばれるものです.
00:38:59例えば、今回のFIFAワールドカップでどこが優勝するのか分かりません.
00:39:03そこで主催者は、48チームを12のグループに分けました.
00:39:11そしてラウンド32、現在まさにラウンド32が行われています.
00:39:16次にラウンド16、準々決勝、準決勝、そして決勝へと進みます.
00:39:21つまり彼らがやっているのは、問題をより小さな単位に分割し、有用な結果を前進させることです.
00:39:30同じアナロジー、あるいは同じアルゴリズムを使って、このモデルの最適化やその他の複雑な仕組みを理解していきます.
00:39:38それでは始めましょう.
00:39:41H100 GPUが1台あるとします.
00:39:46オープンソースモデルの「GPT OSS 120B(1,200億パラメータ)モデル」を使いたいのですが、
00:39:54現在、確かBF16で学習されており、重みのサイズは240ギガバイトです.
00:40:02どうすればよいでしょうか?
00:40:04これが私たちが抱えている問題です.
00:40:07まず第一に、240ギガバイトのモデルと80ギガバイトのH100があります.
00:40:16そして、複数のGPUではなく、1つのGPUだけに収めなければなりません.
00:40:21では、どうすればいいでしょうか?
00:40:22簡単なステップとしては、単に圧縮することです.
00:40:27しかし、どのように圧縮すべきでしょうか?
00:40:29それがもう一つの課題です.
00:40:30BF16からFP8に圧縮した場合、サイズは約120ギガバイトになります.
00:40:38しかし、私たちのGPUであるH100の容量は依然として80ギガバイトです.
00:40:42そのため、さらにMXFP4へと圧縮したのだと思います.
00:40:49その結果、サイズは約65ギガバイトになるようです.
00:40:53このように圧縮という手段が取れますが、疑問が生じます.
00:40:59ここで先ほどの「ダチョウのアルゴリズム」の登場です.
00:41:03大型モデルをより小さなサイズに圧縮しても、性能の損失はないものと仮定するのです.
00:41:10次に、この点について、なるほど。
00:41:16このスライドでは、Mistral 7Bを使用しています.
00:41:20つまり、70億パラメータのモデルです.
00:41:22小さなモデル、70億パラメータですね.
00:41:25これを2バイトで掛け合わせると、モデルの重さは約14となります.
00:41:3114.5ギガバイトとなり、H100やA40にも余裕で収まります.
00:41:38次にできることとして、Mistral 7BをFP16のままにする代わりに、int8、int4、nf4といった異なる量子化手法を適用できます.
00:41:53基本的には、ダチョウのアルゴリズムを使い、品質の低下などは一切ないと思い込むだけです.
00:42:01しかし、何らかの外部ベンチマークでテストを行い、それが実際に機能しているかどうかを数学的にも証明しなければなりません.
00:42:10これは「学習後量子化(PTQ)」と呼ばれる領域に入ります.
00:42:16ファインチューニングの最中にこれを行うことも可能です.
00:42:20こうした量子化は、ファインチューニング時にも実施できます.
00:42:22これは「量子化認識学習(QAT)」の範疇に入ります.
00:42:25それでは次の問題に移りましょう.
00:42:31ここには巨大な行列があります.
00:42:37例えば、1000×1000次元の行列Aと、もう一つの1000×1000の行列を想像してください.
00:42:51これら2つの行列を掛け合わせる場合、演算回数は1000の3乗になります.
00:43:00これは計算上のボトルネックとなります.
00:43:06そのため、行列の掛け算は高速であり、かつメモリを節約できるものであってほしいわけです.
00:43:13では、どうすればよいでしょうか?
00:43:15巨大な行列があります.
00:43:17よし、こちらの4096×4096の行列を取り上げてみましょう.
00:43:234096×4096のサイズにおいて、処理を高速化しメモリを節約するという問題を解決するために何をするべきでしょうか?
00:43:33まず第一に、先ほどの「ワールドカップ・アルゴリズム」を使います.
00:43:37適当な数値を決めて、ブロックを垂直に分割するのです.
00:43:42何を選ぼうとも大した問題ではありません.
00:43:45例えば、4096列があるとします.
00:43:51これを1列あたり128列ずつのグループに分割します.
00:43:57つまり、128、128、128、128、128と垂直に分割します.
00:44:034096をこのように分割すると、32個のブロックが得られます.
00:44:09では、このように分割すると何が起きるでしょうか?
00:44:13垂直方向に分割することで、複数のGPUを使用して処理を高速化できるようになります.
00:44:21このような手法は「マルチヘッド・アテンション」と呼ばれます.
00:44:26他に何ができるでしょうか?
00:44:29先ほど言及したダチョウのアルゴリズムのように、大きな行列が存在します.
00:44:36私たちの主な問題はサイズです.
00:44:39したがって、32個の垂直ブロックをすべて維持する代わりに、31個のブロックを切り捨てるというアプローチが取れます.
00:44:49そして、1つのブロックだけで、すべてのクエリを処理するのに十分であると仮定するのです.
00:44:57損失はほぼ無視できる程度になります.
00:45:00こうして私たちはこのアルゴリズムに行き着きました.
00:45:04このアルゴリズムは「マルチクエリ・アテンション」と呼ばれます.
00:45:08ご覧の通り、私たちは今、2つの両極端な手法の間にいます.
00:45:121つはマルチヘッド・アテンションであり、32個のブロックに分割して異なるGPUを使用したり、並列処理を行ったりします.
00:45:22そしてもう一方は、31個のブロックを単に捨て去るというものです.
00:45:26これをマルチクエリ・アテンションと呼んでいます.
00:45:31このように両極端があるため、私たちはその中間地点を見つけるべきです.
00:45:3831個すべてを捨てるのではなく、いくつかのブロックをグループ化するという方法が考えられます.
00:45:49そして、類似したブロックは類似した種類のクエリに注意を向けるだろうと仮定するのです.
00:45:58こうした技術は「グループド・クエリ・アテンション(GQA)」と呼ばれ、現在非常に人気があります.
00:46:04Mistralや他のモデルにおいても、このグループド・クエリ・アテンションが機能しています.
00:46:11ここまでで、私たちには大きな行列があることを理解しました.
00:46:16それを好みの方法で分割し、いくつかの数学的計算を行うことで、
00:46:19損失がほぼ無視できるレベルであることを証明できます.
00:46:23では、他に何ができるでしょうか?
00:46:25そのあとに、このグループド・クエリ・アテンションを経て、
00:46:34ご覧の通り、大きな行列があります.
00:46:38一方はキーであり、もう一方はバリューです.
00:46:42その行列を潜在ベクトルに圧縮してみましょう.
00:46:47そして、潜在ベクトルから元の行列へと再構築するためのアルゴリズムを考案します.
00:46:55このような戦略は、まさにこの範疇に入ります.
00:46:59マルチヘッド潜在アテンションです.
00:47:02しかし、RoPE(Rotary Position Embedding)には位置依存性がある一方で、こちらは位置非依存的な性質を持つため、再びいくつかの問題が生じます.
00:47:10そのため、マッピングできるようにキー側にも何らかのインデックスを含める必要があります.
00:47:16しかし繰り返しになりますが、根本的な問題は、なぜそれほど大きな行列同士を掛け合わせているのかという点です.
00:47:25なぜなら、アテンション機構とはまさに、各トークンがあらゆるトークンに注意を向ける仕組みになっているからです.
00:47:33では、過去のすべてのトークンに注意を向けるのではなく、自分にとって重要なトークンだけに注意を向けてはどうでしょうか.
00:47:42このように、この分野は今進化しています。
00:47:46これはスパース、DeepSeekのスパースアテンションに該当します。
00:47:51ですので、はい。
00:47:53そして、ええ、それでは、わかりました。
00:47:56次です。
00:47:59はい、では次はフラッシュアテンションです。
00:48:02フラッシュアテンションでは、主な問題点として、
00:48:09現在では、というか今やほとんどの人がフラッシュアテンションを使用していますが、2022年や2023年頃の
00:48:20仕組みはこうでした。
00:48:23どう動いていたかというと、このQとK、クエリとキーの行列がHBMにありました。
00:48:34それをまず、私たちのテンソルコアにロードし、いくつかの計算を行ってから、HBMに書き戻していました。
00:48:47そして、このプロセスが何度も繰り返されます。
00:48:51フラッシュアテンションで何が行われたかというと、行列全体をかけ合わせるのではなく、
00:48:59まるで、ブロック分割アルゴリズムのように、大きな行列を小さなタイルに分割し、
00:49:05その小さなタイルだけをSRAMに載せて高速に掛け算処理を行い、
00:49:13オンラインソフトマックスを計算するために3つの変数を追跡し続けるというものです。
00:49:20はい、これは数学的な話ですが、マルチヘッドアテンションにおいて、もしそれが524 kV用だとしたら、
00:49:34それはどれくらいのグルーピングを望むかによります。例えば、32のkVヘッドの代わりに8つのkVヘッドだけを使いたい場合、
00:49:474倍の圧縮率を得ることができます。これがマルチヘッド・ラテント・アテンションです。
00:49:54この数式は、モデルに何層あるかによってモデルごとに異なります。
00:50:00オリジナルのDeepSeekの論文では、確か128次元、正確な次元数は覚えていませんが、それに基づいて、
00:50:11次元として512を使用し、RoPEインデックス用に64を使用した1つのラテントベクトルを用いており、
00:50:23マルチヘッドアテンションよりも56倍高い圧縮率になることを示しています。
00:50:32わかりました。
00:50:33はい、これはトレードオフの図です。ここではリニアアテンションやMambaについてはまだお話ししていなかったと思います。
00:50:50主な問題はこれらすべての行列乗算であり、現在誰もがアテンションを使用しています。
00:50:56将来的に、トークンを逐次生成するのではなく、例えばすべてを同時に生成できる拡散モデルを使用するなどして、アテンションを使いたくないとなった場合、
00:51:07これらすべてのアルゴリズムも変化するでしょう。
00:51:14しかしここでは、さらに2つ、リニアアテンションとMambaがあります。
00:51:19このスライドによると、何も圧縮しない場合、MHAは単にプロセスを並列化しているだけです。
00:51:29そのため品質の低下がなく優れています。そしてグループド・クエリ・アテンションがあり、これはおそらくほぼすべてのモデルがGQAやDSAのようなものを使用していると思います。
00:51:42はい。
00:51:43アテンションメカニズムのスコアカードでも同じことを提供していると思います。MHAは品質が良く、スループットもそこそこです。
00:51:56グループド・クエリ・アテンションについてはユースケースにもよりますが、品質はマルチヘッドアテンションとほぼ同様であるものの、ユースケースも非常に重要です。
00:52:10はい、マルチ・クエリ・アテンションは極端な例の1つです。
00:52:13理由はわかりませんが、私たちは1つのブロックしか必要とせず、すべてのクエリがその小さなブロックを参照すると仮定しているだけです。
00:52:24そのため、MQAの品質はそれほど優れていません。
00:52:29そしてこのマルチヘッド・ラテント・アテンションですが、DeepSeekモデルを試したことがあるなら、スライディングウィンドウを除いて品質面で素晴らしい仕事をしていると思います。
00:52:44これらはすべて、ウィンドウを調整するなどのテクニックです。すべてを掛け合わせる代わりに、リニアアテンションはまずすべてを要約してから参照すると言い、Mambaは単なる状態空間モデルです、はい。
00:53:09モデルの最適化についても、ここには2つのノートブックがあります。
00:53:28それでは、こちらに移動する必要があります。
00:53:35よし、量子化のデモについてですが、これはもう実行されましたか?いいえ。
00:53:51これを実行してみます。
00:53:54よし、モデルをロードしています。Mistral 7Bのようなモデルです。
00:54:10これはFP16のベースラインでのものです。
00:54:20待ってください。
00:54:21実行されましたか?
00:54:21待って。
00:54:22実行された?
00:54:23わかりました。
00:54:24つまり、ええ、2ミリ秒で実行されました。
00:54:27これは実行された?
00:54:28よし。
00:54:29そう、今回はFP16精度でそのモデルを取得しています。
00:54:35よし。
00:54:36つまり、ええ、2ミリ秒で実行されました。
00:54:40これは実行された?
00:54:41よし。
00:54:42そう、今回はFP16精度でそのモデルを取得しています。
00:54:47Wi-Fiが。
00:54:58時間がかかりそうです。
00:55:03わかりました。
00:55:08はい、Hugging Faceから重みをダウンロードしているからです。
00:55:14は?
00:55:17そう、Colabはオンラインで実行されているので。
00:55:22はい。
00:55:23Hugging Face経由でネットワークコールを行い、取得する必要があるためです。
00:55:30どうかわかりませんが、ダウンロードに時間がかかっているようです。
00:55:35よし。
00:55:36わかりました。
00:55:37よし。
00:55:38わかりました。
00:55:39よし。
00:55:40ここでは、FP16精度の場合、メモリサイズが約15GB前後であることがわかります。
00:56:00タルムードが話していたように、int8による2倍の圧縮を行おうとしています。
00:56:15よし。
00:56:16すると、メモリサイズが0.7GB、0.5GBほどに減っているのがわかります。
00:56:21これは、KVキャッシュが成長するためのメモリをより多く確保できるようになったことを意味します。
00:56:27つまり、より長いコンテキスト長に対応できるようになるか、より多くの同時ユーザーを処理できるようになるということです。
00:56:36したがって、int4で行うと、基本的に4倍の圧縮を行うことになります。
00:56:41そのため、4倍圧縮ではさらに少なくなります。
00:56:453〜4GB程度になると思います。
00:56:50そう、4.5GBです。
00:56:51そして、はい。
00:56:52つまりこれは、待ってください。
00:56:53これは基本的なプロットで、これらは理論上の数値です。
00:57:09ここではスループットのテストなどは行っていません。
00:57:12しかし通常は、メモリが増加するのがわかるでしょう。
00:57:15したがって、多少高いスループットも得られるはずです。
00:57:21私たちが調査したいくつかのベンチマークでは、int8圧縮に見られる特徴でした。
00:57:26スループットは確かに低くなります。
00:57:32わかりました。
00:57:33それから、アテンションメカニズムに関するデモもあります。
00:57:42では、アテンションについて、わかりました。
00:57:45これを実行する必要があります。
00:57:58わかりました。
00:57:59実行されました。
00:58:02おっと。
00:58:03待って。
00:58:04なぜGPUが検出されないと表示されるのだろう?
00:58:09GPUが検出されるはずなのですが。
00:58:18おっと。
00:58:19わかりました。
00:58:29待って。
00:58:30待って。
00:58:30待って。
00:58:50これは驚きです。
00:58:57何らかの理由でGPUを検出できていないようです。
00:59:05ここにはGPUがあるのですが。
00:59:11わかりました。
00:59:12気にしないでください。
00:59:14はい。
00:59:14しかし、ここでの基本的な考え方は、マルチヘッドからグループド・クエリ・アテンション、そしてMLAへと、
00:59:26異なるアテンションメカニズムを使用して計算を圧縮する方向に移行しようとするものです。
00:59:33いくつかの最適化が見られるようになります。
00:59:38昨日の夜、いくつかベンチマークを行っていました。
00:59:43この部分を訂正したいのです。
00:59:45つまり、56倍ではありませんでした。
00:59:4814倍でした。
00:59:50基本的には、デモの計算においてレイヤー数を掛け合わせるのを忘れていたというミスがありました。
01:00:02はい。
01:00:03申し訳ありません。
01:00:04したがって、このMLAは、マルチヘッドアテンションと比較して約14倍の節約になります。
01:00:15ペインポイント、基礎、そしてモデル最適化という最適化の一面を理解したところで、次はサービング側で何ができるかについてお話したいと思います。
01:00:31まず第一に、簡単なデコードステップを実行するとき、モデルの重みをプルし、すべての前トークンのキーおよびバリューベクトルを再計算していることがわかりました。
01:00:50すべてのトークンについてすでにそれらのベクトルを計算しているにもかかわらずです。
01:00:55そのため、間違いなく多くの計算の無駄が生じています。
01:01:02そして、その時間計算量を分析してみると、O(N^2)になることがわかります。
01:01:07それを解決する方法は、メモリとの古典的なトレードオフです。
01:01:12トークンに対するこれらのベクトルのメモリを維持し、そのメモリを参照することができます。
01:01:19そのため、そのメモリはKVキャッシュと呼ばれていました。
01:01:24そして、フローはこのようになります。
01:01:27そしてこのKVキャッシュに基づき、実に4つの最適化が可能になりました。
01:01:35最初のものはページド・アテンションに関するものです。
01:01:42では、現在何が違い、何が問題なのでしょうか?
01:01:45GPUに入力として複数のリクエストを送信する場合、これらのリクエストはバッチ処理されます.
01:01:52各リクエストには、連続したメモリ領域が割り当てられます.
01:01:58例えば、分かりやすく例として2KVが割り当てられるとしましょう.
01:02:05しかし、実際のリクエストに必要なのは1KVだけだったとします.
01:02:11そのため、メモリの断片化が50%ほど発生することになります.
01:02:19そしてこの断片化が、基本的にメモリの無駄につながります。
01:02:24つまり、メモリ内にはさらに多くのリクエストを処理できる空きスペースがあったにもかかわらず、連続したメモリブロックを探していたために処理できなかったということです.
01:02:36そこで、OSの仕組みからヒントを得ることにしました.
01:02:41論理メモリを維持しつつ、物理メモリを基本として持つという方法です.
01:02:47論理メモリ上では、すべてのトークンのKVベクトルが連続しているかのように感じられます.
01:02:59しかし実際には、異なる物理アドレスにマッピングされます.
01:03:06そのため、メモリを大幅に節約するのに非常に役立ちました。
01:03:11そしてこれが可能になったのは、メモリをブロックの集合として捉えているからです.
01:03:18リクエストの必要に応じて、それらのブロックを動的に割り当てることになります.
01:03:22新しいトークンが次々と到着し、そうしたメモリが必要になるにつれて割り当てられます.
01:03:27もう一つのレバーとなるのが、バッチで複数のリクエストを送信している時の状況です.
01:03:39GPUはそれらのリクエストを受け取ります.
01:03:42しかし、そのバッチ内のすべてのリクエストが完了するまで、新しいバッチを受け付けません.
01:03:49そのため、図としてはページネーションに似たものになります.
01:03:52しかしここでは、GPUがいつ次のバッチを受け取れるようになるかが重要になります.
01:03:59つまり、GPUが完全にアイドル状態になっている期間が存在するのです.
01:04:04そして、それを何とか解決したいわけです.
01:04:08そのためのアイデアとして、「連続バッチング(Continuous Batching)をやろう」ということになりました.
01:04:17また、連続バッチ処理によりスループットも大幅に向上しました。多くのリクエストを迅速に処理できるようになったからです。
01:04:24GPUが常に稼働状態にあり、アイドル状態で遊んでいないことを確実に維持できます.
01:04:33その結果、計算リソースを節約できるわけです.
01:04:363つ目は、プレフィックスキャッシュ(prefix caching)です.
01:04:39KVキャッシュが、単一リクエスト内でのトークン間での計算を節約するのに役立ったのを覚えているでしょう.
01:04:46しかし、複数のリクエスト間で同じトークンが存在する場合はどうでしょうか?
01:04:53それに対して、どのように計算を節約すればよいのでしょうか?
01:04:55vLLMによって導入されたプレフィックスキャッシュは、まさにそれに対処するものです.
01:05:04そして3つ目は…実際には4つ目ですね.
01:05:10モデルの量子化についてお話しましたが、KVウェイト(重み)も量子化することができます.
01:05:21つまり、キーおよびバリューのベクトルに必要なスペースが少なくて済むようになります.
01:05:28それはつまり、メモリ内でより多くのキーおよびバリューベクトルを扱えるということです.
01:05:32結果として、より多くのトークンを処理できるようになります.
01:05:34つまり、より大きなコンテキスト長に対応できるようになります.
01:05:37そして、より高品質なモデルを提供できるということです.
01:05:41そして、これらすべてはもうvLLMに備わっています。
01:05:51わざわざ車輪の再発明をする必要はないのです.
01:05:56このvLLMをプロダクション環境にデプロイすれば、その成長を実感できるはずです。
01:06:03次に、私たちが実施したベンチマークについてです.
01:06:08このベンチマークは…データがあるか確認させてください.
01:06:14ここにあります.
01:06:17デモですね.
01:06:22このベンチマークの実行には約1時間かかります。vLLMサーバーを継続的に停止・再起動したり、モデルをロードしたりする必要があるためです.
01:06:35そのためテストにはかなり時間がかかりますが、私たちが何をしているのかここで実際にお伝えすることができます.
01:06:41まず、Mistral 7Bのようにモデルは同じものに保っています.
01:06:46そして、送信する入力質問のセットを用意しています.
01:06:53これらをプロンプトと考えてください.
01:06:56次に、サーバーが起動しているかどうかを確認するなどのヘルパー関数がいくつかあります.
01:07:01このサーバーとはvLLMサーバーのことです.
01:07:04さらに、vLLMのメトリクスを取得するためのヘルパー関数もあります.
01:07:09それらのメトリクスがどのようなものかについても説明します.
01:07:14その後、多くのベンチマークなどが続きます.
01:07:17そして、KVの使用量などを測定する必要があります.
01:07:22これらが、このようなヘルパー関数群です.
01:07:24ベースラインは非常にシンプルです.
01:07:26Hugging Faceのベースラインを使用しています.
01:07:29これは、テキストをLLMにそのまま送信し、レスポンスを受け取るという素朴なものです.
01:07:36ここでいくつかの結果が見られます.
01:07:38Hugging Faceのスループットは、秒間約51トークンであることがわかりました.
01:07:44最初のトークンまでの時間(TTFT)は54でした.
01:07:46そして、トークン間レイテンシは19でした.
01:07:49これらはすべてH100上で実行されたものです.
01:07:56次に、非常にデフォルトなvLLMサーバーを起動します.
01:08:00vLLMではデフォルトで、ページネーション、連続バッチング、KVキャッシュが提供されます.
01:08:08つまり、これら3つの機能がデフォルトで存在しています.
01:08:13そして、それらのベンチマークを比較してみると、スループットがほぼ15倍になっていることがわかります.
01:08:211秒あたりにより多くのトークンを処理できるようになります.
01:08:24そして、最初のトークンまでの時間も向上します.
01:08:34また、トークン間レイテンシは低下します.
01:08:38そして、ユーザー数やコンテキストに対するKVキャッシュの使用量は確実に増加します.
01:08:43ここで、これにプレフィックスキャッシュを適用してみます.
01:08:51プレフィックスキャッシュを有効にすると、スループットがさらに向上することがわかります.
01:08:57TTFT(初回のトークン生成時間)は短縮されます.
01:08:59トークン間レイテンシはほぼ同じです.
01:09:02そして、ユーザー数に対するKVキャッシュの使用量は減少する傾向にあります.
01:09:09コンテキストに対する使用量は減少しません.
01:09:12ほぼ同等です.
01:09:14これもほぼ同等だと思います.
01:09:16そこまで大きな違いではありません.
01:09:19さらにその上に、KV量子化を適用した場合を見てみましょう.
01:09:25スループットはほぼ同等であることがわかります.
01:09:33初回トークンまでの時間も同様です.
01:09:36トークンレイテンシも同様です.
01:09:39しかし、KV使用量は実際に低下します.
01:09:42これは、キーとバリューの空間を量子化したためです.
01:09:49そして次に、タンマイ(Tanmay)が説明する「推論先読み(speculative decoding)」という概念があります.
01:09:54それらをベンチマークしてみると、KV使用量がやや少なくなっていることも確認できます.
01:10:06結果自体はほぼ同じですが.
01:10:08全体として、これらが各指標の数値となります.
01:10:21画面を縮小したほうがよさそうですね.
01:10:25なるほど.
01:10:26縮小できないですね.
01:10:27縮小します.
01:10:28動きませんね.
01:10:29素晴らしい.
01:10:30というわけで、これがvLLMのベンチマーク結果です.
01:10:35ちなみに、これが本番環境のデフォルト設定になります.
01:10:38他のエンジンについて議論する際にも、その決定木を共有する予定です.
01:10:48それでは、この上にさらに実装できる他の推論最適化手法について話を進めましょう.
01:10:58そして、他にもどのようなソリューションが登場したのかについてです.
01:11:02それでは再度、タンマイを呼びたいと思います.
01:11:07彼からこうした最適化のいくつかについて話してもらいます.
01:11:11おっと、失礼.
01:11:12本当に申し訳ありません.
01:11:13スライドを表示していませんでした.
01:11:26何でしたっけ?
01:11:27なるほど.
01:11:28わかりました.
01:11:29完璧です.
01:11:30どれでしたっけ?
01:11:31推論先読み(Speculative Decoding)ですね.
01:11:32はい.
01:11:33ありがとう、ハーシャル.
01:11:34はい.
01:11:35これらすべてが推論先読みに関するものです.
01:11:40これらはすべて、いわば同じ炭酸飲料の異なるフレーバーのようなものです.
01:11:46つまり、このテクニックはデコーディングアクセラレーターに属します。
01:11:51まず、推論デコーディングについて話してきましたが、自己推論やEagle、Medusaといった他のバリエーションもあります。
01:12:01個人的には、このEagleアルゴリズムが良いと思っています.
01:12:05それでは推論先読みから始めましょう.
01:12:06はい.
01:12:07わかりました.
01:12:08それでは、推論先読みとは何かから始めます.
01:12:09主な問題は、トランスフォーマーアーキテクチャでは、これらすべてのトークンが1つずつ順番にシーケンシャルに生成される点にあります.
01:12:26小さなモデルを使用し、その小さなモデルに4つか5つのトークンを生成させてみてはどうでしょうか?
01:12:37そして、この教師モデル、あるいは私たちのワールドカップアルゴリズムに倣って「レフェリー」と呼べるモデルが検証します.
01:12:43レフェリーが、何個のトークンを受け入れるかを決定するわけです.
01:12:48このループが継続的に実行されます.
01:12:51私たちの前提としては、このような手法がうまく機能する特定のドメインが存在するというものです.
01:12:59例えばコーディングなどが挙げられます。そこでは創造性がほとんど求められません.
01:13:05コードや構文はそれぞれほぼ似通っています.
01:13:08そのため、役に立つ可能性があります.
01:13:10ですが、개인적으로 테스트해 본 결과, 이 speculative decoding은 전혀 유용하지 않았습니다.
01:13:18하지만 self-speculative decoding 같은 다른 기법들, 즉 교사 모델도 하나의 헤드, 보조 헤드를 가지고 기본 모델이나 작은 모델이 하는 것과 비슷한 작업을 수행하는 기법들이 있죠.
01:13:35하지만 그 후에 EGLE이 나왔습니다. EGLE 1, 2, 3... 버전이 얼마나 있는지는 모르겠지만, 토큰을 생성하는 대신 작은 모델을 학습시키고 메인 모델 레이어 중 하나에서 피처를 가져옴으로써 토큰 대신 이 피처를 생성하도록 하자는 방식입니다.
01:14:02따라서 EGLE은 이러한 다른 기술들과 비교했을 때 더 뛰어납니다.
01:14:10그리고 또 다른 하나는 MEDUSA인데, 이는 이 모든 토큰들을 병렬로 생성하자는 방식입니다.
01:14:17좋습니다, 자 여기 이 슬라이드에서요.
01:14:21네.
01:14:22다음 슬라이드요.
01:14:24알겠습니다.
01:14:25좋습니다.
01:14:26네, 알겠습니다.
01:14:27좋습니다.
01:14:28이제 프리픽스 캐싱(prefix caching)에 대해 알아보겠습니다.
01:14:34사람들이 이 정적 프리픽스 캐싱을 사용하고 있는지 잘 모르겠네요.
01:14:39하지만 핵심 문제는, 프리픽스 캐싱은 가끔 우리가 타이핑을 하다가 작은 실수를 할 때 발생합니다.
01:14:47이 표준적인 정적 프리픽스 캐싱은 기본적으로 프롬프트를 받아 해싱을 수행합니다.
01:14:53그리고 다음에 사용자가 비슷한 질문을 하면 그 해시를 매칭하려고 시도하죠.
01:14:58따라서 해시가 일치하면, 그 모든 k와 v를 다시 연산하는 대신 스토리지에서 바로 가져옵니다.
01:15:09하지만 아시다시피 우리는 가끔 실수를 하거나 단어이나 글자 하나를 바꾸기도 합니다.
01:15:15그렇게 되면 캐시 미스율이 아주 높아지게 됩니다.
01:15:21그래서 등장한 것이 바로 이 래딕스 트리(Reddix tree)입니다.
01:15:25래딕스 트리는 에이전트로 인해 매우 인기를 얻고 있습니다.
01:15:30제 생각엔 거의 모든 사람들이 에이전트를 다루고 있으며, 대부분의 연산은 테스트 타임, 즉 추론 과정에서 이루어집니다.
01:15:38비슷한 종류의 질문과 프롬프트를 계속해서 던지는 과정이죠.
01:15:42예를 들어, '당신은 전문 소프트웨어 엔지니어입니다'를 200번 곱한 것 같은 상황입니다.
01:15:48이러한 루프가 에이전트 같은 시스템 내부에서 계속 반복됩니다.
01:15:55그렇기 때문에 유사한 내용들을 래딕스 트리에 유지하거나 저장하는 것이 필수적입니다.
01:16:03따라서 래딕스 트리는 프리픽스 트리의 발전된 버전으로, 분기가 없는 노드는 압축(collapse)하는 방식입니다.
01:16:17동일한 작업을 계속 반복하는 이러한 유형의 작업에서요.
01:16:24이 래딕스 트리는 큰 도움이 되며, sglang은 프리픽스 캐싱을 위해 이러한 알고리즘을 사용합니다.
01:16:35좋습니다, 네, 그리고 또 다른 것이 있습니다.
01:16:38바로 Tensor RT-LLM입니다.
01:16:41이것은 매우 혼란스럽습니다.
01:16:42제가 처음 시작했을 때 정말 헷갈렸습니다.
01:16:46도대체 Tensor RT-LLM이란 무엇인가?
01:16:49네, Tensor RT는 표준 SDK 같은 것입니다.
01:16:55Tensor RT-LLM은 그냥 추론 엔진일 뿐이죠.
01:16:59VLLM이나 sglang처럼 말입니다.
01:17:01하지만 문제는 이것이 NVIDIA와 관련이 있다는 점입니다.
01:17:05그들은 모든 레이어와 모든 문제를 최적화했습니다.
01:17:10제가 월드컵 알고리즘에서 언급했듯이, 그들은 모든 것을 해체하고 하드웨어 수준에서도 모든 것을 최적화했습니다.
01:17:18네, 알겠습니다, 다음이요.
01:17:23네, 이번 워크숍을 위해 저희는 어떤 것이 가장 좋은지 벤치마킹도 진행했습니다.
01:17:33저희의 설정은 대략 이랬습니다.
01:17:36테스트는 두 가지 종류로 진행했습니다.
01:17:39첫 번째는 에이전트 테스트가 없는 경우로, 그냥...
01:17:44ShareGPT 데이터셋을 사용해 VLLM과 sglang을 이용해 질문을 던져보는 방식이었습니다.
01:17:57좋습니다.
01:18:05네, 좋습니다.
01:18:07화면을 좀 확대하겠습니다.
01:18:12네, 좋습니다.
01:18:13네, 이번 워크숍에서는 H100을 사용했으며, 첫 번째 테스트에서는 다음과 같이 질문했습니다.
01:18:23ShareGPT에서 질문을 가져와 VLLM과 sglang에 입력해 본 결과, 어느 쪽이 더 우수한지 통계적으로 유의미한 차이는 실제로 없음을 발견했습니다.
01:18:34따라서 두 시스템 모두 거의 비슷한...
01:18:37초당 요청 처리량(RPS), TTFT, 그리고 지연 시간(latency) 측면에서 비슷하게 충족하고 있습니다.
01:18:43하지만 유일한 차이점은 에이전트 브랜칭(agentic branching) 과정에서 나타났습니다.
01:18:50우리가 한 작업은 '당신은 세상에서 가장 뛰어난 소프트웨어 엔지니어입니다' 같은 질문을 던진 것입니다.
01:18:59그래서 도시의 교통 체증 문제를 해결해 달라는 식의 요청이었죠.
01:19:04그 후, 이를 LLM에 입력했습니다.
01:19:08LLM이 일부 출력을 생성합니다.
01:19:10그리고 2라운드도 진행했습니다.
01:19:13이 LLM이 출력을 생성한 후, 2라운드에서는 특별히 다음과 같이 언급하도록 했습니다.
01:19:22제안서를 검토하고 1점부터 10점까지 평점을 매겨달라고요.
01:19:28이렇게 두 턴의 작업을 수행했으며, 이 루프가 계속해서 반복됩니다.
01:19:35このような標準化されたワークフローでは、プロンプトやコンテキストエンジニアリングが重要になってくることが分かりました。
01:19:47따라서 이러한 에이전트 브랜칭을 적절히 수행하면 SGLang이 3~4배 더 우수하다는 것을 알 수 있습니다.
01:19:54물론 이것도 설정에 따라 다를 수 있습니다.
01:19:58직접 해보시면 다른 결과를 얻으실 수도 있습니다.
01:20:02알겠습니다.
01:20:03네.
01:20:04그래서 제 생각에는...
01:20:06GitHub에 업로드했었나요?
01:20:08네.
01:20:09좋습니다.
01:20:10네.
01:20:11PDF도 드라이브에 올라와 있습니다.
01:20:15슬라이드와 같은 링크입니다.
01:20:18그럼 여기서 간략한 요약을 해드리겠습니다.
01:20:22표준 API 워크로드 처리량 측면에서는 VLLM과 SGLang이 동일하다는 것을 보실 수 있습니다.
01:20:31따라서 만약...
01:20:33표준 워크로드가 있다면 무조건 VLLM을 선택하세요.
01:20:36어차피 프로덕션의 기본값입니다.
01:20:38하지만 Tanmay가 말했던 것처럼 에이전트 워크로드를 구축하려고 할 때 SGLang이 진가를 발휘합니다.
01:20:50그리고 모든 이점들을 제공해주죠.
01:20:55네, 그렇습니다.
01:20:58VLLM을 기본값으로 유지하세요.
01:21:00하지만 에이전트 워크로드가 있다면 SGLang으로 전환을 시도해보세요.
01:21:05VLLM에 만족하지 못하신다면 말입니다.
01:21:09알겠습니다.
01:21:10잠시만요...
01:21:15잠깐만요.
01:21:18좋습니다.
01:21:21그리고 또...
01:21:29120B 모델로 진행된 비교가 있습니다.
01:21:33GPT OSS 120B에 대한 벤치마크 말이죠.
01:21:36이것은 PlayPy에서 준비한 벤치마크입니다.
01:21:42여기에 블로그 링크도 있습니다.
01:21:46오, 좋네요.
01:21:48알겠습니다.
01:21:49네.
01:21:50그들도 유사한 벤치마크를 수행했으며, 그 안에 TensorRT-LLM을 포함시켰습니다.
01:21:57확실히 이러한 벤치마크들을 살펴보며 여러분의 유스케이스에 가장 적합한 것이 무엇인지 파악해보실 수 있습니다.
01:22:05앞서 언급했듯이 TensorRT는 최고 수준의 하드웨어 성능을 발휘하도록 하드웨어 측면에서도 최적화를 시도합니다.
01:22:16그리고 사용할 엔진을 결정할 때, VLLM, SGLang, TensorRT 중에서 고민하다 보면 새롭게 등장하는 새로운 엔진들도 존재합니다.
01:22:29NVIDIA Dynamo도 확실히 그 중 하나죠.
01:22:43이들은 에이전트 세션 라우팅을 위한 것이기도 합니다.
01:22:49Hugging Face도 항상 존재합니다.
01:22:51간단히 훑어볼 수 있죠.
01:22:53그리고 최근 스탠퍼드에서 제안된 MSTAR 엔진이라는 것도 있습니다.
01:23:00멀티모델용 NVIDIA Dynamo도 있고요.
01:23:05확실히 이런 것들도 탐색해 보실 수 있습니다.
01:23:08간단히 요약하자면, 우리는 베이스라인부터 시작합니다.
01:23:15우리의 유스케이스에 맞는 모델이 무엇인지 찾으려고 노력하죠.
01:23:22DeepSeek을 선택할 수도 있습니다.
01:23:27Mistral 7B 같은 건 고르지 마세요.
01:23:30제 말은, 좋지 않다는 겁니다.
01:23:32하지만 네.
01:23:35따라서 모델을 고르고 더 적은 메모리를 사용하면서도 더 큰 모델을 더 작은 메모리에 맞추고 싶어 합니다.
01:23:44그래야 GPU 비용을 절감할 수 있으니까요.
01:23:47그래서 양자화(quantization) 같은 작업들을 수행할 수 있습니다.
01:23:51그런 다음 후드 아래에서 올바른 서빙 엔진을 사용하여 모든 서빙 최적화를 적용할 수 있습니다.
01:23:58그렇게 하면 정말로 원하는 처리량을 확보할 수 있습니다.
01:24:07그리고 집에 돌아간 후에 해볼 수 있는 것으로, 여기서 모든 자료를 다 다룰 수는 없기 때문에 다양한 어텐션 메커니즘이나 이러한 엔진들과 같은 소스 정보에 대해 읽어보는 것을 추천합니다.
01:24:27온라인에 있는 다양한 벤치마크들도 직접 읽어보려고 노력해 보세요.
01:24:34그리고 심층 가이드나 다음 단계로, KV 축출(eviction) 전략 등에 대해 학습하는 과정들이 많이 있습니다.
01:24:45현재 세계는 별도의 KV 캐시 엔지니어링 영역을 구축하는 방향으로 나아가고 있습니다.
01:24:50따라서 그 안에서 무슨 일이 일어나고 있는지 이해해야 합니다.
01:24:52KV 축출, 캐시 압축, 하이브리드 메모리 같은 것들이죠.
01:24:57이와 관련해서 정말 많은 솔루션들이 나오고 있습니다.
01:25:01그러니 항상 기반이나 기초, 혹은 제1원칙(first principles)을 고수하려고 노력하세요.
01:25:08그리고 어떤 솔루션이 어떤 문제를 해결하는지, 그리고 여러분의 유스케이스에서 실제로 그 문제를 해결할 필요가 있는지 살펴보세요.
01:25:17그 다음에는 분산 LLM 추론이 있는데, 이는 완전히 또 다른 까다로운 주제입니다.
01:25:26모든 내부 구조를 살펴보고 핸즈온을 진행하려면 아마 2시간짜리 워크숍이 따로 필요할 것입니다.
01:25:40네, 그리고 이것은 AI 엔지니어 뉴욕 세션을 위해 제안하고자 하는 내용으로, LLM 추론의 고급 섹션을 더 깊이 파고드는 것입니다.
01:25:51따라서 이번 워크숍은 초급 및 중급 수준에 더 초점을 맞췄습니다.
01:25:55このフォームでは、ご意見やご感想に加え
01:26:02特定のセクションの改善点などについてもぜひフィードバックをお寄せください。
01:26:09また、ニューヨークでの開催をご希望の方も、ぜひ参加希望をご登録ください。
01:26:22え?
01:26:24どういうことだ?
01:26:27おっと。
01:26:32ちょっと確認させてください。
01:26:37分かりました。
01:26:38え?
01:26:39はい。
01:26:40URLは機能していますよね?
01:26:41はい。
01:26:42QRコードではなくて?
01:26:43なるほど。
01:26:44両者をリンクさせ忘れたかもしれません。
01:26:45分かりました。
01:26:46了解です。
01:26:46はい。
01:26:47ですので、もしよければ。
01:26:49分かりました。
01:26:50了解です。
01:26:51はい。
01:26:52ですので、もしよければ。
01:26:53分かりました。
01:26:54はい。
01:26:55分かりました。
01:26:56了解です。
01:26:57はい。
01:26:58ですので、もしよければ。
01:26:59ちょっと。
01:27:00分かりました。
01:27:00分かりました。
01:27:01了解です。
01:27:02はい。
01:27:02ですので、もしよければ。
01:27:03ちょっと。
01:27:04分かりました。
01:27:05それで大丈夫です。
01:27:06えー、それでは、このあたりで本日のワークショップを締めくくらせていただきたいと思います。
01:27:13皆様からもたくさんのご質問があることと思います。
01:27:14それらについてはオフラインで対応可能です。
01:27:15えー、集まって、その質問について話し合うこともできます。
01:27:16はい。
01:27:17もちろんです。
01:27:18もちろんです。
01:27:19えー、皆様、ありがとうございました。
01:27:20ご参加ありがとうございます。
01:27:21えー、本当に。
01:27:22えー、皆様、ありがとうございました。
01:27:23えー、皆様、ありがとうございました。
01:27:24ご参加ありがとうございます。
01:27:25えー、皆様、ありがとうございました。
01:27:26ご参加ありがとうございます。
01:27:27えー、本当に。
01:27:28あ、分かりました。
01:27:29えー、分かりました。
01:27:30それで大丈夫です。
01:27:31えー、それでは、このあたりで本日のワークショップを締めくくらせていただきたいと思います。
01:27:33えー、それでは、このあたりで本日のワークショップを締めくくらせていただきたいと思います。
01:27:36皆様からもたくさんのご質問があることと思います。
01:27:39それらについてはオフラインで対応可能です。
01:27:41えー、集まって、えー、その質問について、えー、話し合うこともできます。
01:27:42はい、もちろんです。
01:27:43えー、皆様、ありがとうございました。
01:27:44えー、本当に有意義な時間でしたし、皆様にお越しいただき感謝しています。
01:27:49えー、本当にありがとうございました。
01:27:50はい、ありがとうございます。
커뮤니티 글
아직 글이 없습니다. 이 영상에 대한 첫 번째 글을 작성해 보세요!
이 영상에 대해 글쓰기