HUOXIU

LLM を展開する前に GPU メモリ要件を計算して最適化するにはどうすればよいですか?

編集者注:大規模言語モデル(LLM)を導入したいのですが、必要なGPUメモリをどのように見積もればよいかお困りではありませんか?プロジェクト予算が限られている中で、GPUメモリの見積もりが不正確だったために、リソースが無駄になったり、パフォーマンスが不十分になったりした経験はありませんか?こうした問題は、プロジェクトのスケジュールに影響を与えるだけでなく、コスト超過やサービス品質の低下にも直結する可能性があります。

LLM導入における豊富な経験に基づき、本稿ではGPUメモリ要件に対する計算手法を詳細に分析します。モデルパラメータからキーバリューキャッシュ、活性化値からシステムオーバーヘッドまで、各コンポーネントのメモリフットプリントを包括的かつ綿密に解説します。また、メモリの断片化、過剰割り当て、高度なデコードアルゴリズムの追加要件など、メモリ管理の課題についても考察します。これらの問題に対処するため、著者らはPagedAttentionやvLLMといった最適化手法を導入しています。GPUメモリが不足している場合は、スワッピングや再計算といった最適化戦略も活用できます。

著者 | ムハンマド・サード・ウディン

編纂者:岳陽

LLMを本番環境に導入するには、特に必要なコンピューティングリソースを効率的に提供することにおいて、多くの課題が伴います。この分野の経験者であれば、GPUメモリがLLMの実行に不可欠なリソースであることをご理解いただけるでしょう。これらのモデルは大規模であり、推論プロセスは動的であるため、GPUメモリ使用量の計画と最適化には高度な専門知識が求められます。

著者による画像(DallE経由)

GPU メモリ要件を正確に見積もることは、いくつかの理由から重要です。

  • 費用対効果:GPUリソ​​ースは高価です。メモリ要件を過大評価すると不要なハードウェア支出につながり、メモリ要件を過小評価するとシステム障害やパフォーマンスの低下を引き起こす可能性があります。
  • パフォーマンスの最適化: 適切なメモリ管理により、モデルの効率的な操作が保証され、ユーザーのニーズに迅速に対応し、同時処理機能が向上します。
  • スケーラビリティ: ビジネス ニーズが拡大するにつれて、パフォーマンスに影響を与えたり過剰なコストが発生したりすることなくサービスを拡張するには、メモリ要件を正確に理解することが重要になります。

しかし、LLMサービスに必要なGPUメモリを計算するのは簡単ではありません。モデルサイズ、シーケンス長、バッチサイズ、デコードアルゴリズムなど、多くの要因がメモリ使用量に複雑に影響を与えます。さらに、従来のメモリ割り当て方法では、メモリの断片化やキーバリュー(KV)キャッシュなどの動的メモリコンポーネントの非効率的な管理により、大きな無駄が生じることがよくあります。

この記事では、LLMサービスに必要なGPUメモリの計算方法を可能な限り詳細に説明します。メモリ使用量に影響を与える様々な要因を分析し、モデルパラメータとワークロード特性に基づいて、メモリフットプリントを見積もる方法を段階的に説明します。また、Paged AttentionやvLLMといった高度な最適化手法についても解説します。これらの手法は、メモリ消費量を大幅に削減し、処理能力を向上させることができます。この記事を読むことで、LLMのGPUメモリ使用量を計画および最適化する方法を包括的に理解し、実用的なアプリケーションにおいて効率的かつ低コストのLLM導入を実現できるようになります。

01 LLM 推論中に GPU メモリを消費する主なコンポーネントを理解する。

GPUメモリ計算手法を習得するには、各要素がどのようにGPUメモリを消費するかを理解することが重要です。メモリ使用量を理解することで、リソースをより適切に計画し、最適化することができます。LLM推論において、GPUメモリを消費する主な要素には、重み(モデルパラメータ)、キーバリューキャッシュメモリ、アクティベーション、一時バッファ、そしてオーバーヘッド(並列処理や分散コンピューティングを学んだことがある方なら、この概念は既にご存知かもしれません)などがあります。

1.1 モデルパラメータ(重み)

モデルパラメータとは、ニューラルネットワークがトレーニング中に学習する数値(重みとバイアス)です。これらのパラメータは、モデルが入力データを処理して出力を生成する方法を定義します。

モデルサイズがGPUメモリに与える影響

  • 直接相関: モデルが大きくなるほど (パラメータが多くなるほど)、これらの重みを保存するために必要な GPU メモリが大きくなります。
  • メモリ計算: 半精度 (FP16) 形式を使用する場合、各パラメータには通常 2 バイトが必要です。これは推論では一般的であり、精度を大幅に損なうことなくメモリを節約できます。

これらのモデルを見てみましょう:

  1. 34.5億個のパラメータを持つ小さなLLM:
  • 必要なメモリ: 34.5億 x 2バイト = 69 MB。単一のGPUで容易にサポートできます。
  1. ここで、llama2-13b モデルを使用すると、
  • 130億個のパラメータの場合、必要なメモリは130億バイト × 2バイト = 26 GBとなります。この場合、40GBのメモリを搭載したA100 GPUが必要になります。
  1. 1750億のパラメータを持つと言われるGPT-3モデルを見てみましょう。
  • 必要メモリ:1750億×2バイト=350GB。モデルの重みを保存するだけでも少なくとも9個のGPUが必要です。

GPT-3 以降のモデルでは、モデルの並列処理を使用してモデル パラメータを複数の GPU に分散することが不可欠であることを覚えておいてください。

1.2 キーバリュー(KV)キャッシュメモリ

キーバリュー(KV)キャッシュは、生成シーケンスにおける各トークンに必要な中間表現を保存します。簡単に言うと、モデルがトークンを生成するたびに、コンテキストを維持するために以前のトークンを記憶する必要があります。KVキャッシュは、これまでに生成された各トークンのキーと値のベクトルを保存することで、モデルが過去のトークンを再計算することなく効率的に処理できるようにします。

動作原理:

  • キーと値: アテンション メカニズムでは、モデルは各トークンのキー ベクトルと値ベクトルを計算します。
  • ストレージ: これらのベクトルは KV キャッシュに保存され、後続のステップで新しいトークンを生成するために使用されます。

シーケンスの長さと同時リクエストの影響:

  • シーケンスが長くなる: トークンの数が増えると、KV キャッシュ内のエントリが増え、メモリ使用量が増加します。
  • 複数のユーザー: 複数のリクエストを同時に処理すると、必要なキー値キャッシュ メモリが飛躍的に増加します。

各トークンの KV キャッシュ サイズを計算します。

各トークンの KV キャッシュ サイズを決定する方法を分析してみましょう。

  1. 各トークンのキー値キャッシュ コンポーネント:

キーベクトル(レイヤーごとに1つのキーベクトル)と値ベクトル(レイヤーごとに1つの値ベクトル)

  1. 各トークンのベクトルの合計数:

モデル層数(L)×非表示層サイズ(H):モデルの深さ×各ベクトルの次元。

再び llama-13b モデルを例に挙げると、モデルには次のような特性があると仮定します。

  • モデル層数(L):40層
  • 非表示層のサイズ (H): 5120 次元 (このサイズのモデルでは一般的な次元)。
  1. 各トークンのメモリ使用量を計算します。

i. キーベクトル:

  • 総数: L層 × H寸法 = 40 × 5120 = 204,800
  • メモリサイズ: 204,800 x 2 バイト (FP16) = 409,600 バイト (または 400 KB)

ii. 値ベクトル:

  • キーベクトルと同じ: 400 KB

iii. 各トークンの合計KVキャッシュ:

  • キーベクトル + 値ベクトル: 400 KB + 400 KB = 800 KB

ここで、出力に 2000 個のトークンが含まれている場合を考えてみましょう。

800 KB/トークン × 2000 トークン = 出力シーケンスあたり 1.6 GB

同時リクエストが 10 件ある場合 (モデルが同時に 10 人のユーザーにサービスを提供する場合): 1.6 GB / 出力シーケンス × 10 出力シーケンス = 16 GB の KV キャッシュ メモリ。

KVキャッシュは、シーケンス長と同時リクエスト数の増加に比例して増加します。ある論文[1]によると、KVキャッシュはGPUメモリの最大30%以上を消費する可能性があることがわかりました。

1.3 アクティベーション値と一時バッファ

アクティベーションとは推論中のニューラルネットワーク層の出力を指し、一時バッファは中間計算に使用されます。アクティベーションとバッファは通常、モデルの重みやキーバリューキャッシュよりもメモリ消費量が少なくなります。

これらは GPU メモリ全体の約 5 ~ 10% を使用する場合があります。

活性化値はサイズは小さいものの、モデルが各層の出力を計算するために不可欠です。これらはフォワードパス中に生成され、破棄されますが、それでも十分なメモリ割り当てを必要とします。

1.4 メモリオーバーヘッド

追加のメモリオーバーヘッドは、メモリの割り当てと使用が非効率なために発生します。以下に概要を示します。

メモリの断片化:

  • 内部断片化: これは、割り当てられたメモリ ブロックが完全に使用されていない場合に発生します。
  • 外部断片化: 時間の経過とともに空きメモリが小さなブロックに断片化され、必要なときに大きな連続したメモリ ブロックを割り当てることが難しくなります。

計算プロセス中の中間ステップ:

  • 一時データ: 行列の乗算などの操作により、大量のメモリを消費する一時テンソルが作成されることがあります。

非効率的なメモリ管理の影響:

  • パフォーマンスの低下: メモリの浪費により、システムが処理できる同時リクエストの数が制限される可能性があります。
  • スループットの低下: メモリ管理が非効率だと遅延が発生し、ユーザーへのサービス応答の全体的な速度が低下する可能性があります。

例: メモリの断片化により 40 GB の GPU 上のメモリの 20% が無駄になっている場合、より多くのリクエストを処理するために使用できた 8 GB のメモリが無駄になっていることになります。

02 コンピューティングGPUメモリ要件

重要な内容を十分に理解できたので、これ以上遅れることなく、完全な GPU メモリ要件を直接計算してみましょう。

ステップバイステップの計算:

あらゆるモデルのメモリ要件を計算するには、モデルの重み、キーバリューキャッシュ、活性化値、一時バッファ、システムメモリのオーバーヘッドなど、ほぼすべての要素を理解する必要があります。llama-2 13Bモデルを例にとると、計算式は次のようになります。

必要なメモリ合計: モデルの重み + キー値キャッシュ + アクティベーション値とシステムメモリのオーバーヘッド

13Bモデルの場合:

モデルの重み = パラメータ数 × パラメータあたりのバイト数

合計KVキャッシュメモリ = トークンあたりのKVキャッシュメモリ × 出力シーケンス長 × 出力シーケンス数

アクティベーション値とシステムメモリのオーバーヘッド = GPUメモリ全体の5~10%

アクティベーション値とシステムメモリのオーバーヘッドは、通常、モデルパラメータとKVキャッシュで使用されるGPUメモリ全体の約5~10%を消費します。このメモリ消費分を予備として、現在計算されているメモリ全体の10%を追加で割り当てることができます。

モデルの重み = 130億 × 2バイト = 26 GB

合計 KV キャッシュメモリ = 800 KB × 8192 * トークン × 10 * 同時リクエスト = 66 GB

アクティベーション値とシステムメモリのオーバーヘッド = 0.1 × (26 GB + 66 GB) = 9.2 GB

*モデルの出力シリーズの長さが 8192 で、並列リクエストが 10 個あると想定します。

必要なメモリ合計: 26 GB + 66 GB + 9.2 GB = 101.2 GB

したがって、llama-2 7B モデルを実行するには、少なくとも 3 つの A100 40GB GPU が必要です。

GPT-3モデルをホストしたい場合(これはクレイジーだとは思いますが;D)、計算方法は同様ですが、今回は一度に1つのリクエストのみが処理されると想定し、OPT-175B[2]モデルのサイズ(96レイヤー、レイヤーあたり12288次元)を基準として使用します。

モデルの重み = 1750億 × 2バイト = 350 GB

合計KVキャッシュメモリ = 4.5 MB × 8192トークン × 1同時リクエスト = 36 GB

アクティベーション値とシステムメモリのオーバーヘッド = 0.1 × (350 GB + 36 GB) = 38.6 GB

必要なメモリ合計:350 GB + 36 GB + 38.6 GB = 424.6 GB。A100が約11台分になります😐。

GPT-4 が 1 兆個のパラメータを持つモデルであると仮定すると、2.3 TB のメモリが必要になります。

モデルのサイズとパラメータに関する公開情報に基づいて計算されたメモリ計算テーブルを以下に示します。

著者が計算した表

同様に、モデルを多数のユーザー (たとえば 10 人) に同時にデプロイすると、結果のメモリ内計算テーブルは次のようになります。

著者が計算した表

複数のリクエストを処理する場合、メモリ消費量が大幅に増加します。これは主に、キーバリューキャッシュの大幅な増加が原因です。モデルの重みとシステムメモリのオーバーヘッドは一定であるため、トークン数と同時リクエスト数の増加に伴いキーバリューキャッシュが大幅に増加し、結果としてマトリックスの行数が増加し、メモリ消費量に直接的に影響を及ぼします。

さて、OpenAI[3]やAnthropic[4]の大規模モデルに何百万人ものユーザーがいるシナリオを想像してみてください。

GPUメモリ使用時に直面する3つの課題と最適化戦略

上記の計算を行った後、大規模言語モデル(LLM)の導入時に直面する課題と、これらの課題に対する最新の研究による最適化について議論しなければ、この記事は不完全だと気づきました。多くの人にとって、効率的なGPUメモリ管理技術を理解し、習得することは非常に重要です。以下では、この点について簡単に分析します。

3.1 課題1: メモリの断片化とメモリの過剰割り当て

デプロイメント時には通常、KVキャッシュに静的にメモリを割り当て、各リクエストに対して可能な限り多くのメモリを確保します。しかし、実際の出力シーケンスは実際にはそれよりも短いことが多いにもかかわらず、システムは可能な限り長い出力シーケンスに対してメモリを予約するため、メモリの過剰割り当てが発生することがよくあります。

さらに、メモリの断片化は有効な利用可能メモリを減少させ、システムが同時に処理できるリクエストの数を制限します。メモリの断片化は、内部と外部の2種類に分けられます。内部メモリの断片化とは、割り当てられたメモリブロックが十分に活用されず、未使用のメモリ領域が残ることを指します。一方、外部メモリの断片化とは、空きメモリが時間の経過とともに複数の小さな非連続メモリブロックに断片化され、必要なときに十分な大きさの連続メモリブロックを割り当てることが困難になることを指します。

メモリの非効率的な使用とは、GPUの計算リソースが十分に活用されていないことを意味します。その結果、システムは計算能力ではなくメモリによって制限され、プロセッサ性能が浪費されます。(これは、並列システムや分散システムでは回避すべき問題です。)

3.2 課題2: デコードアルゴリズム

多くのLLMアプリケーションは、出力品質を最適化したり、多様な出力結果を生成するために、高度なデコードアルゴリズムを採用する傾向があります。これらの手法は効果的である一方で、メモリ管理において新たな課題も生じます。例えば、ビームサーチを例に挙げてみましょう。このアルゴリズムは複数の候補出力シーケンス(「ビーム」)を生成し、スコアリング基準に基づいて最も高いスコアを持つシーケンスを保持します。つまり、各「ビーム」には専用のキー値キャッシュが必要となり、メモリ使用量が増加します。同様に、並列サンプリングは、モデルによって生成された確率分布からサンプリングすることで、複数の独立した出力を一度に生成します。各出力にも専用のキー値キャッシュが必要となり、メモリ消費量がさらに増加し​​ます。

動的メモリ割り当てシナリオでは、デコード中に「ビーム」またはサンプル数が変化する可能性があり、予測不可能なメモリ需要が発生します。メモリの断片化や過剰なメモリオーバーヘッドを発生させることなく、メモリを動的に割り当て・解放することは、大きな技術的課題です。さらに、これらのデコード手法はメモリ要件を指数関数的に増加させ、GPUの処理能力を超える場合もあります。GPUメモリが不足すると、システムはデータを低速なCPUメモリやハードディスクに移行する必要があり、処理時間は間違いなく長くなります。

こうした問題に直面して、私たちは次のように考えるかもしれません。

これらの制限をどうしたら克服できるでしょうか?

3.3 ページングされた注意

オペレーティングシステムのメモリ管理に着想を得たPagedAttentionは、仮想メモリのページング原理をキーバリュー(KV)キャッシュ管理に適用します。この手法により、KVキャッシュのデータは、連続したメモリブロックを占有するのではなく、複数の非連続メモリページに分散されます。Pag​​edAttentionは動的なメモリ割り当て戦略を採用し、出力シーケンスの最大長に対応するメモリを事前に確保することなく、実際のニーズに基づいてKVキャッシュにメモリを割り当てます。このアテンションメカニズムにより、異なるメモリアドレスからKVキャッシュデータをスムーズに取得できます。

PagedAttention の利点は、より小さなメモリ ブロックを使用することで、メモリの断片化を効果的に削減し、それによってメモリの断片化によって発生するメモリの無駄を減らし、全体的なメモリ使用率を向上させることです。

3.4 vLLM

簡単に言えば、vLLMはPagedAttentionを基盤とした高スループットLLMサービスシステムです。その主な目的は、推論中にGPUメモリ、特にキーバリューキャッシュを効率的に管理することです。理論上、vLLMはメモリの無駄をほぼゼロにするソリューションを実現します。動的なメモリ割り当てと非連続ストレージにより、メモリの無駄を事実上排除します。また、理論上、単一リクエスト内およびリクエスト間でのキーバリューキャッシュデータの共有もサポートしており、これは高度なデコード手法に特に役立ちます。これを基盤として、vLLMはより大きなバッチサイズとより多くの同時リクエストを処理できるため、全体的なパフォーマンスが向上します。

最適化を施しても、GPUメモリ不足が発生することがあります。vLLMはスワップとレピュテーションによってこの問題に対処します。このメカニズムについて詳しく見ていきましょう。

3.5 KVキャッシュをCPUメモリにスワップする

  • スワッピング: GPU メモリが完全にロードされると、システムは KV キャッシュ データを GPU メモリから CPU メモリに一時的に転送します。
  • アドバンテージ:
    • メモリの軽減: GPU メモリからデータを移動することで、新しいリクエストのためのスペースを確保し、リソース不足により GPU メモリが新しいタスクの実行を妨げないようにします。
  • 料金:
    • レイテンシの増加: CPU メモリのアクセス速度は通常 GPU メモリよりも遅いため、CPU メモリからのデータの読み取りには GPU メモリからのデータの読み取りよりも時間がかかります。
    • データ転送のオーバーヘッド: GPU メモリと CPU メモリ間でデータを転送すると、帯域幅とプロセッサ時間が消費されます。

3.6 再計算

すべてのキー値キャッシュ データを保存する代わりに、必要に応じて再計算します。

  • アドバンテージ:
    • メモリ使用量を削減: メモリに保存する必要があるデータの量を削減します。
  • 料金:
    • 計算負荷の増加: データの再計算には追加の処理能力が必要です。
    • 遅延の影響: 計算負荷が増加すると、応答時間が長くなる可能性があります。

スワッピングと再計算方法の比較表

著者別表

スワッピングまたは再計算をそれぞれ単独で使用する場合、それぞれに利点と欠点がありますが、この 2 つを組み合わせることで、互いの欠点を補い、メモリの節約、計算の削減、レイテンシの低減という点でより理想的なバランスを実現できます。

読んでくれてありがとう!

このブログを楽しんで、新しいことを学んでいただければ幸いです。

著者について

ムハンマド・サアド・ウディン

データ サイエンスは数学の詩であり、データはあなたの愛であり、あなたの詩的な表現を最大限に明瞭に世界に示すためにどのように詩を書くかはあなた次第です。

終わり

今週のインタラクティブコンテンツ🍻

モデルのサイズが大きいために GPU のメモリが不足するという問題が発生したことはありませんか?

🔗記事内のリンク🔗

[1] https://arxiv.org/pdf/2309.06180

[2] https://medium.com/@plienhar/llm-inference-series-4-kv-caching-a-deeper-look-4ba9a77746c8

[3] https://openai.com/

[4] https://www.anthropic.com/

オリジナルリンク:

https://ai.gopubby.com/stop-guessing-heres-how-much-gpu-memory-you-really-need-for-llms-8e9b02bcdb62