大規模言語モデル (LLM) テクノロジーのマスター: 推論の最適化

翻訳链接:LLM テクニックの習得: 推論の最適化 | NVIDIA テクニカル ブログ

大規模モデルに関連する技術記事はGithub リポジトリにまとめられています。ようこそstart!

Transformer レイヤーを積み重ねて大規模なモデルを作成すると、さまざまな言語タスクでの精度の向上、少数ショット学習機能、さらには人間に近い創発機能が実現します。これらの基本モデルのトレーニングにはコストがかかり、推論中に大量のメモリと計算が必要になる可能性があります (定期的なコスト)。現在最も人気のある大規模言語モデル (LLM) のサイズは、数百億から数千億のパラメーターに及び、ユースケースによっては、長い入力 (またはコンテキスト) を取り込む必要がある場合があり、これによりオーバーヘッドも追加されます。

この投稿では、LLM 推論における最も差し迫った課題と、いくつかの実用的な解決策について説明します。読者は、変圧器のアーキテクチャと注意メカニズムについての基本を理解している必要があります。

1. LLM 推論を理解する

最も一般的なデコードのみの LLM (GPT-3 など) は、本質的に次の単語の予測子として、因果モデリングの目標に向けて事前トレーニングされています。これらの LLM は、一連のトークンを入力として受け取り、停止条件が満たされるまで (生成されるトークンの数の制限やストップ ワードに遭遇するなど)、または特別な <end> トークンが生成されます。終了トークン。このプロセスには、事前設定段階とデコード段階の 2 つの段階が含まれます。

トークンは、モデルによって処理される言語のアトミックな部分であることに注意してください。トークンは約 4 文字の英字です。すべての自然言語は、モデルに入力される前にトークンに変換されます。

1.1 事前設定段階または入力処理

事前設定フェーズでは、LLM は入力トークンを処理して、「最初の」トークンの生成に使用される中間状態 (キーと値) を計算します。新しいトークンはそれぞれ以前のすべてのトークンに依存しますが、すべての入力が既知であるため、高度に並列化された行列演算となり、GPU を効率的に使用できます。

1.2 デコード段階または出力の生成

デコードフェーズでは、LLM は停止条件が満たされるまで、一度に 1 回の自己回帰で出力トークンを生成します。各出力トークンには、前の反復までのすべての出力状態 (キーと値) が必要です。これは、GPU の計算能力を最大限に活用しない行列ベクトル演算など、事前に設定された入力処理と比較されます。実際に消費される時間ではなく、データ (重み、キー、値、アクティベーション) がメモリから GPU に転送される速度によってレイテンシーが決まります。つまり、これはメモリが制限された操作です。

このホワイトペーパーで説明する推論の課題と対応するソリューションの多くには、このデコード段階の最適化 (効率的なアテンション モジュール、キーと値の効率的な管理など) が含まれます。

異なる LLM は異なるトークナイザーを使用する可能性があるため、それらの間で出力トークンを比較することは簡単ではない可能性があります。推論スループットを比較する場合、2 つの LLM が 1 秒あたり同様のトークンを出力したとしても、異なるトークナイザーを使用している場合は等しくない可能性があります。これは、対応するトークンが異なる数の文字を表す可能性があるためです。

1.3 バッチ処理

GPU 使用率と効果的なスループットを向上させる最も簡単な方法は、バッチ処理を使用することです。複数のリクエストが同じモデルを使用するため、重みのメモリ コストが分散されます。大量のデータを一度に処理するために GPU に転送すると、GPU リソースの使用率が向上します。

ただし、バッチ サイズは特定の制限までしか増やすことができず、その時点でメモリ オーバーフローが発生する可能性があります。これを防ぐには、キー/値 (KV) キャッシュと LLM メモリ要件を確認してください。

従来のバッチ処理 (静的バッチ処理とも呼ばれます) は最適ではありません。これは、バッチ内のリクエストごとに LLM が異なる数のトークンを生成する可能性があり、トークンが異なれば実行時間も異なるためです。したがって、バッチ内のすべてのリクエストは、最も長いトークンの処理が完了するまで待機する必要がありますが、世代の長さの大きな違いによってさらに悪化する可能性があります。これを軽減する方法としては、わずかに動的なバッチ処理などがあります。

1.4KVキャッシュ

デコード段階での一般的な最適化は、KV キャッシュです。デコード ステージでは各タイム ステップで単一のトークンが生成されますが、各トークンは前のトークンのキー テンソルと値テンソル (プレフィル時に計算された入力トークンの KV テンソル、および現在のタイム ステップの前に計算された新しい KV テンソルを含む) に依存します。 。 量) 。

タイム ステップごとにすべてのトークンに対してこれらのテンソルを再計算することを避けるために、これらのテンソルを GPU メモリにキャッシュできます。各反復で新しいトークンを計算する必要がある場合、トークンは次の反復で使用するために実行中のキャッシュに追加されます。一部の実装では、モデルの各層に KV キャッシュがあります。

ここに画像の説明を挿入します

図 1 KV キャッシュのメカニズム

1.5 LLM メモリ要件

実際、LLM の GPU メモリに対する需要は主にモデルの重みと KV キャッシュです。

  • モデルの重み: モデル パラメータがメモリを占有します。たとえば、16 ビット精度 (FP16 または BF16) でロードされた 70 億個のパラメータを持つモデル (Llama2-7B など) は、約 7B * sizeof(FP16) ~= 14 GB のメモリを占有します。
  • KV キャッシュ: セルフ アテンション テンソルのキャッシュは、冗長な計算を避けるためにメモリを占有します。

バッチ処理を使用する場合、バッチ内の各リクエストの KV キャッシュは個別に割り当てる必要があり、大量のメモリを占有する可能性があります。次の式は、現在最も一般的な LLM アーキテクチャの KV キャッシュ サイズを示しています。

$$
各トークンの KV キャッシュ サイズ (バイト) = 2 * (num_layers) * (num_heads * dim_head) * precision_in_bytes

$$

最初の因数 2 は、K 行列と V 行列を表します。通常、 (num_heads * dim_head) の値は、Transformer の hidden_​​size (またはモデルの次元 d_model) と同じです。これらのモデル プロパティは通常、構成ファイル内にあります。

このメモリ サイズは、入力バッチの入力シーケンス内の各トークンに必要です。半精度と仮定すると、KV キャッシュの合計サイズは次のように求められます。

合計 KV キャッシュ サイズ (バイト) = ( b a t c h _ s i z e ) ∗ ( s e q u e n ce _ l e ng th ) ∗ 2 ∗ ( n um _ l a y ers ) ∗ ( hi d en _ s i z e ) ∗ (FP 16 ) のサイズ 合計 KV キャッシュ サイズ (バイト) = ( バッチ\_size) * (シーケンス\_length) * 2 * (num\_layers) * (hidden\_size) * sizeof(FP16)KV缓存大小(字节)=(tch _size)(ifque nce_le ngth)2(num_ laはい)(こんにちはdden _size)siゼオf( FP16)

たとえば、16 ビット精度の Llama 2 7B モデルでバッチ サイズが 1 の場合、KV キャッシュのサイズは 1 * 4096 * 2 * 32 * 4096 * 2 バイト、これは約 2 GB です。

KV キャッシュを効率的に管理することは困難な作業です。メモリ要件はバッチ サイズとシーケンスの長さに応じて直線的に増加し、迅速に拡張できます。したがって、サービス可能なスループットが制限され、長いコンテキスト入力に対して課題が生じます。これが、この記事で紹介するいくつかの最適化の背後にある動機です。

2. モデルの並列化により LLM が拡張される

デバイスごとのモデルの重みのメモリ フットプリントを削減する 1 つの方法は、モデルを複数の GPU に分散することです。メモリと計算を分散することで、より大規模なモデルや入力のより大きなバッチを実行できるようになります。モデルのトレーニングまたは推論にはモデルの並列処理が必要であり、トレーニングと推論用の単一デバイスよりも多くのメモリ (レイテンシまたはスループット) が必要です。モデルの重みがどのように分割されるかに応じて、モデルを並列化する方法がいくつかあります。

データ並列処理は、以下に挙げる他の手法と組み合わせてよく使用される手法でもあることに注意してください。この場合、モデルの重みが複数のデバイスにコピーされ、入力 (グローバル) バッチ サイズが各デバイスでマイクロバッチに分割されます。より大きなバッチを処理することにより、全体の実行時間が短縮されます。ただし、これはトレーニング時間の最適化であり、推論中にはあまり関係がありません。

2.1 パイプラインの並列処理

パイプライン並列化モデルを(垂直に)チャンクにスライスします。各チャンクには、別のデバイスで実行されるレイヤーのサブセットが含まれます。。図 2a は、モデルが順次に分割され、すべてのレイヤーの 4 分の 1 のサブセットが各デバイスで実行される 4 方向のパイプラインを示しています。 1 つのデバイス上の一連の操作の出力は次のデバイスに渡され、その後のブロックの実行が続行されます。 F n F_n Fn B n B_n Bn はそれぞれ機器を表します n n n での順方向および逆方向の伝播。モデルの重みを保存するためのメモリ要件は、各デバイスで 4 つに分割されます。

このアプローチの欠点は、処理の逐次的な性質により、前のレイヤーの出力 (アクティブ化、グラデーション) を待機している間、一部のデバイスまたはレイヤーがアイドル状態のままになる可能性があることです。 a>。これにより、非効率的な前方パスと後方パス、つまり「パイプライン バブル」が発生する可能性があります。図 2b の白い空白の領域は、パイプラインの並列処理によって生成されたパイプライン バブルであり、デバイスがアイドル状態で十分に活用されていません。

図 2c に示すように、マイクロバッチ処理により、この状況をある程度軽減できます。入力されたグローバル バッチ サイズはサブバッチに分割され、1 つずつ処理され、最終的に勾配が蓄積されます。 F n , m F_{n,m} に注意してください。Fnm B n , m B_{n,m} Bnm は、デバイス上のバッチの順方向パスと逆方向パスをそれぞれ表します。 この方法ではダクトの気泡のサイズは小さくなりますが、完全に除去することはできませんnm

ここに画像の説明を挿入します

図 2 パイプラインの並列処理

2.2 テンソル並列処理

テンソル並列化モデルの各レイヤーを(水平方向に)スライスして、さまざまなデバイスで実行できる小さな独立した計算ブロックにします。。 Transformer の主要コンポーネントであるアテンション ブロックおよび多層パーセプトロン (MLP) 層は、Tensor を使用して並列化できます。マルチヘッド アテンション ブロックでは、各ヘッドまたはヘッドのグループを異なるデバイスに割り当てることができるため、それらを独立して並行して計算できます。

ここに画像の説明を挿入します

図 3 Tensor 並列化 MLP とセルフアテンション

図 3a は、MLP テンソル並列処理の 2 つの層の例を示しています。各層は丸いボックスで表されます。最初の層では、重み行列 A A A分为 A 1 A_1 1 A 2 A_2 2 。入力 X の場合、同じバッチ内の異なるデバイスで計算できます X A 1 XA_1 XA1 および $XA_2 。ここで、 f は ID 演算です。これにより、各デバイスに重みを保存するためのメモリ要件が半分になります。リダクション演算。f は恒等演算です。これにより、各デバイスに重みを保存するためのメモリ要件が半分になります。操作を減らす fidtg$ は、2 番目の層の出力を結合します。 操作。これにより、各デバイスに重みを保存するためのメモリ要件が半分になります。リダクション操作yitne

図 3b は、セルフ アテンション層における Tensor 並列処理の例です。複数のアテンション ヘッドは本質的に並列であり、デバイス間で分割できます。

2.3 シーケンスの並列性

テンソル並列化には制限があります。レイヤを独立した管理可能なブロックに分割する必要があります。LayerNorm Dropout などには適していません。代わりに、テンソル並列処理で複製されます。 LayerNorm Dropout は計算コストが低くなりますが、(冗長な) アクティベーションを保存するために大量のメモリを必要とします。

大規模変圧器モデルにおけるアクティベーション再計算の削減に示すように、これらの演算は入力シーケンスでは独立しており、これらの演算 ので、メモリ効率が向上します。これをシーケンス並列処理と呼びます。 「シーケンス ディメンション」に沿って分割できる

ここに画像の説明を挿入します

図 4、トランスフォーマー層のテンソル並列化とシーケンス並列化

モデルの並列化手法は固有のものではなく、組み合わせて使用​​できます。これらは、LLM の GPU ごとのメモリ フットプリントの拡張と削減に役立ちますが、アテンション モジュールに特化した最適化手法もあります。

3. 注意メカニズムの最適化

スケーリング ドット積アテンション (SDPA、スケーリング ドット積アテンション) 操作は、 querykey のペアを出力にマップします。次に示します。論文にはと記載されています。 必要なのは注意だけ

3.1 マルチヘッドアテンション (MHA)

SDPA の拡張機能として、3 つの変換テンソルはそれぞれ Q、K、V に対して線形変換を実行します。これらの変換は元のテンソルのサイズを変更しません により、モデルは異なる位置にある異なる表現部分空間からの情報に共同で焦点を当てることができます。これらの部分空間は独立して学習されるため、モデルは入力内のさまざまな位置をより深く理解できるようになります。

図 5 に示すように、複数の並列アテンション操作の出力が結合され、線形投影されて結合されます。それぞれの並列アテンション層は「ヘッド」と呼ばれ、このアプローチはマルチヘッド アテンション (MHA) と呼ばれます。

8 つの並列アテンション ヘッドが使用される場合、各アテンション ヘッドの次元は削減されます (例: d _ mod e l / 8 d\_model/8 d_model/8)。这使得计算成本与单头注意力相似。

ここに画像の説明を挿入します

図 5 ドット積アテンション (左) とマルチヘッド アテンション (右)、複数の SDPA ヘッドを並列にスケーリングする図

3.2 マルチクエリ アテンション (MQA)

MHA の推論最適化の 1 つは、高速トランスフォーマー デコーディングで提案されているように、マルチクエリ アテンション (MQA) と呼ばれます。複数のアテンション ヘッド間でキーと値を共有します。 a>。以前と同様に、クエリ ベクトルは複数回投影されます。

MQA で実行される計算量は MHA と同じですが、メモリから読み取られるデータ (キー、値) の量は以前の数分の一です。これにより、メモリ帯域幅によって制限されている場合でも、コンピューティング利用率が向上します。また、メモリ内の KV キャッシュのサイズも削減され、より大きなバッチ サイズに対応できる余地が残ります。

キーヘッダーを削減すると、精度が低下する可能性があります。さらに、推論時にこの最適化を利用する必要があるモデルは、MQA を有効にしてトレーニングする必要があります (または、少なくともトレーニング量の約 5% を使用して微調整する)。

3.3 グループ化された注意 (GQA)

グループ化クエリ アテンション (GQA) は、キーと値をいくつかのクエリ ヘッドのセットに投影することで、MHA と MQA の間のバランスをとります (図 6)。各グループ内では、マルチクエリ アテンションのように動作します。

図 6 は、複数のキーと値のヘッドを備えたマルチヘッド アテンションを示しています (左)。グループ化されたクエリ アテンション (中央) には複数のキーと値のヘッダーがありますが、クエリ ヘッダーの数は少なく、メモリ要件とモデルの品質のバランスが保たれています。マルチクエリ アテンション (右) には単一のキーと値のヘッダーがあり、メモリの節約に役立ちます。

ここに画像の説明を挿入します

元々 MHA を使用してトレーニングされたモデルは、元のトレーニング計算の一部を使用して GQA で「アップトレーニング」できます。 MQA に近い計算効率を維持しながら、MHA に近い品質を実現します。 Llama 2 70B は GQA を利用するモデルの例です。

MQA や GQA などの最適化は、保存されるキー ヘッダーと値ヘッダーの数を減らすことで、KV キャッシュに必要なメモリを削減します。 KV キャッシュの管理方法は依然として非効率的である可能性があります。次のセクションでは、アテンション モジュール自体を最適化する代わりに、より効率的な KV キャッシュ管理手法を紹介します。

3.4 フラッシュアテンション

アテンション メカニズムを最適化するもう 1 つの方法は、特定の計算の順序を変更して GPU のメモリ階層をより効果的に利用することです。ニューラル ネットワークはレイヤーの観点から説明されることが多く、ほとんどの実装はこの方法でレイアウトされ、入力データに対して一度に 1 つの計算を順番に実行します。これは常に最適なパフォーマンスをもたらすとは限りません。メモリ階層のより高い、よりパフォーマンスの高いレベルに入った値に対してより多くの計算を実行する方が有益な場合があるためです。

実際の計算中に複数のレイヤーを融合すると、GPU がメモリの読み取りと書き込みに必要な回数が最小限に抑えられ、ニューラル ネットワーク内の異なるレイヤーの一部であっても、同じデータを必要とする計算がグループ化されます。

非常に人気のある融合は、I/O 対応の Exact Attendant アルゴリズムである FlashAttend です。詳細をご覧ください。FlashAttend: IO 認識を使用した高速でメモリ効率の高い Exact Attendance。正確なアテンションとは、数学的には標準のマルチヘッド アテンション (マルチクエリ アテンションおよびグループ化クエリ アテンションに利用可能なバリアントあり) と同じであるため、既存のモデル アーキテクチャ (すでにトレーニング済みのモデルであっても) に変更することなく置き換えることができることを意味します。

I/O 認識とは、操作を融合するときに、前述したメモリ移動コストの一部を考慮することを意味します。特に、FlashAttendant は、行列全体を段階的に部分的に計算してその間の中間値を書き出すのではなく、「タイリング」を使用して、最終的な行列の一部を一度に完全に計算して書き出すのです。

図 7 は、40 GB GPU 上のタイル化された FlashAttendant 計算パターンとメモリ階層を示しています。右側の画像は、アテンション メカニズムのさまざまなコンポーネントを融合および並べ替えることによって生じる相対的な高速化を示しています。

ここに画像の説明を挿入します

図 7 40 GB GPU 上のタイル FlashAttend 計算モデルとメモリ階層

4. KVキャッシュの効率的なページング管理

入力のサイズは予測できないため、可能な最大の入力 (サポートされるシーケンス長) を考慮して KV キャッシュが静的に「オーバープロビジョニング」されることがあります。たとえば、モデルでサポートされる最大シーケンス長が 2,048 の場合、リクエストの入力および生成される出力のサイズに関係なく、サイズ 2,048 のデータがメモリに保持されます。このスペースは連続的に割り当てることができますが、多くの場合、その大部分が未使用となり、メモリの浪費や断片化が発生します。この予約されたスペースは、リクエストの存続期間中占有されます。

ここに画像の説明を挿入します

図 8 過剰なプロビジョニングと非効率的な KV キャッシュ管理によるメモリの無駄と断片化

オペレーティング システムのページングからヒントを得た PagedAttendant アルゴリズムは、連続するキーと値をメモリ内の不連続な空間に保存できます。各リクエストの KV キャッシュを固定数のトークンを表すブロックに分割し、これらのブロックを不連続に格納できます。

アテンションの計算中に、これらのチャンクはレコード インデックスを使用してフェッチされます。新しいトークンが生成されると、新しいブロックが割り当てられます。これらのブロックのサイズは固定されており、異なるリクエストに異なる割り当てが必要になるなどの課題によって引き起こされる非効率性が排除されます。これによりメモリの無駄が大幅に制限され、バッチ サイズを大きくできるようになります (したがってスループットが向上します)。

5. モデル最適化技術

これまで、LLM がメモリを消費するさまざまな方法、複数の異なる GPU にメモリを割り当てるいくつかの方法、アテンション メカニズムと KV キャッシュの最適化について説明してきました。モデルの重み自体を変更することで各 GPU のメモリ使用量を削減できる、さまざまなモデル最適化手法もあります。 GPU には、これらの変更された値の演算を高速化する専用のハードウェアもあり、モデルをさらに高速化します。

5.1 量子化

量子化は、モデルの重みとアクティベーション精度を低減するプロセスです。ほとんどのモデルは 32 または 16 ビットの精度でトレーニングされ、各パラメーターとアクティベーション要素は 32 または 16 ビットのメモリ (単精度浮動小数点) を占有します。ただし、ほとんどの深層学習モデルは、値あたり 8 ビットまたはそれ以下のビットで効率的に表現できます。

図 9 は、1 つの可能な定量化方法の前後の値の分布を示しています。この場合、丸めによって精度の一部が失われ、クリッピングによってダイナミック レンジの一部が失われるため、値をより小さい形式で表現できます。

ここに画像の説明を挿入します

図 9 考えられる定量化方法の前後の値の分布

モデルの精度を下げると、さまざまなメリットが得られます。モデルが占有するメモリ領域が少ない場合は、同じ量のハードウェアでより大きなモデルを実行できます。量子化は、同じ帯域幅でより多くのパラメータを転送できることも意味し、帯域幅が制限されたモデルの高速化に役立ちます。

LLM には、アクティベーション、重み、またはその両方の精度を低下させるさまざまな量子化手法が多数あります。定量的重みはトレーニング後に固定されるため、非常に簡単です。ただし、アクティベーションは依然として高い精度で維持されるため、パフォーマンス上の問題が残る可能性があります。 GPU には INT8 と FP16 の数値を乗算するための専用のハードウェアがないため、実際の操作では重みをより高い精度に変換し直す必要があります。

アクティベーション、Transformer ブロック、ネットワーク層への入力を定量化することも可能ですが、これには独自の課題があります。アクティベーション ベクトルには外れ値が含まれることが多く、そのダイナミック レンジが効果的に増加し、重みよりも低い精度でこれらの値を表現することがより困難になります。

1 つのオプションは、モデルに代表的なデータセットを渡し、特定のアクティベーションを他のアクティベーションよりも高い精度で表すことを選択することにより、これらの外れ値が発生する可能性のある場所を見つけることです (LLM.int8() )。もう 1 つのオプションは、簡単に定量化できる重みのダイナミック レンジを借用し、その範囲をアクティベーションで再利用することです。

5.2 スパーシティ

量子化と同様に、多くの深層学習モデルは、 に近い特定の値を 0 自体で枝刈りしたり置き換えたりすることに対して堅牢であることが証明されています。疎行列とは、0 要素が多く含まれる行列です。これらの行列は圧縮形式で表現できるため、完全な密行列よりも占有するスペースが少なくなります。 0

ここに画像の説明を挿入します

図 10. 圧縮形式で表されたスパース行列。ゼロ以外のデータ値とそれに対応する 2 ビットのインデックスで構成されます。

特に GPU には、4 つの値のうち 2 つがゼロで表される、ある種の構造化されたスパース性に対するハードウェア アクセラレーションが備わっています。スパース表現を量子化と組み合わせて実行速度を向上させることもできます。大規模な言語モデルをスパース形式で表現する最適な方法を見つけることは、依然として活発な研究分野であり、将来の推論速度を向上させるための有望な方向性を提供します。

5.3 蒸留

モデルのサイズを削減するもう 1 つの方法は、蒸留と呼ばれるプロセスを通じて、モデルの知識をより小さなモデルに転送することです。このプロセスには、より大きなモデル (教師) の動作を模倣するように小さなモデル (学生と呼ばれます) をトレーニングすることが含まれます。

蒸留モデルの成功例には、言語理解能力の 97% を維持しながら BERT モデルを 40% 圧縮するDistilBERT があります。 60%増加しました。

LLM での蒸留は活発な研究分野ですが、ニューラル ネットワークへの一般的なアプローチは、ニューラル ネットワークでの知識の蒸留

  • 生徒ネットワークは、出力間の差を測定する損失関数を使用して、より大規模な教師ネットワークのパフォーマンスを反映するようにトレーニングされます。目標には、生徒の出力を真のラベルと一致させる原始損失関数も含まれる場合があります。

  • マッチングの教師出力は、最後の層 (logits と呼ばれる) または中間層のアクティブ化のいずれかになります。

図 11 は、知識の蒸留の全体的なフレームワークを示しています。教師の logits は、生徒が蒸留損失を使用して最適化するためのソフト ターゲットです。他の蒸留方法では、教師から知識を「蒸留」するために他の損失尺度が使用される場合があります。

ここに画像の説明を挿入します

図 11、知識蒸留の一般的な枠組み

蒸留の代替アプローチは、教師が合成したデータを使用した LLM での生徒の教師ありトレーニングです。これは、人間による注釈が不足している場合、または利用できない場合に特に役立ちます。段階的に蒸留していきます!さらに、基本的な事実としてのラベルに加えて、基本原則も LLM の教師から抽出されます。これらの理論的根拠は、データ効率の高い方法で小規模な LLM をトレーニングするための中間推論ステップとして機能します。

今日の最先端の LLM の多くは、その結果を他の LLM をトレーニングするために使用することを禁止する制限的なライセンスを持っているため、適切な教師モデルを見つけることが困難になっていることに注目する価値があります。

6. モデル提供テクノロジー

モデルの実行は、メモリ帯域幅、特に重みによって制限されることがよくあります。前述したモデルの最適化をすべて適用した後でも、依然としてメモリが制限される可能性があります。したがって、モデルの重みをロードするときに、それらをできるだけ多く処理します。言い換えれば、並列処理を試してみましょう。次の 2 つのアプローチが可能です。

  • 動的バッチ処理 (実行中のバッチ処理): 複数の異なるリクエストを同時に実行します。
  • 推論推論): シーケンスの複数の異なるステップを並行して実行して、時間を節約します。

6.1 动态批处理(In-flight batching

LLM には独特の実行特性があり、実際にはバッチ リクエストを効率的に処理することが困難になる可能性があります。モデルは、多くの異なるタスクに同時に使用できます。チャットボットでの単純な Q&A の応答から文書の概要やコード ブロックの生成に至るまで、ワークロードは非常に動的であり、出力サイズは桁違いに異なります。

この多用途性により、リクエストをバッチ処理し、それらを並行して効率的に実行することが困難になります。これは、ニューラル ネットワークにサービスを提供するための一般的な最適化です。これにより、一部のリクエストが他のリクエストより早く完了する可能性があります。

これらの動的負荷を管理するために、多くの LLM サービス ソリューションには、連続バッチ処理または動的バッチ処理と呼ばれる最適化されたスケジューリング手法が含まれています。これは、LLM のテキスト生成プロセス全体がモデル上の複数の実行反復に分割できるという事実を利用しています。

動的バッチ処理を使用すると、サーバー ランタイムはバッチ全体が完了するのを待ってから次のリクエスト セットに進むのではなく、完了したシーケンスをバッチから即座に削除します。。その後、他のリクエストがまだ進行中に、新しいリクエストの実行が開始されます。したがって、動的バッチ処理により、実際のユースケースにおける全体的な GPU 使用率が大幅に向上します。

6.2 预测任務(推測的推論

予測推論は、投機的サンプリング、補助生成、またはチャンク並列デコードとも呼ばれ、LLM を並列実行するもう 1 つの方法です。通常、GPT スタイルの大規模言語モデルは、テキスト トークンを 1 つずつ生成する自己回帰モデルです。

によって生成される各タグは、その前にあるすべてのタグに依存してコンテキストを提供します。これは、通常の実行では、同じシーケンスから複数のトークンを並行して生成することは不可能であり、n+1 個のトークンを生成する前に n 番目のトークンが生成されるまで待つ必要があることを意味します。

図 12 は、予測推論の例を示しています。アドホック モデルは、並列検証または拒否の複数の将来のステップをアドホックに予測します。この場合、一時モデルの最初の 2 つの予測トークンは受け入れられますが、最後の予測トークンは拒否され、生成が続行される前に削除されます。

ここに画像の説明を挿入します

図 12、予測推論の例

予測サンプリングが解決策を提供します。この方法の基本的な考え方は、「より安価な」プロセスを使用して、いくつかのトークンの長さの一時的なシーケンスを生成することです。次に、必要な実行ステップの「予測」コンテキストとして安価な一時シーケンスを使用して、メインの「検証」モデルの複数のステップが並行して実行されます。

検証モデルが一時シーケンスと同じトークンを生成する場合、検証モデルはこれらのトークンを出力として受け入れることができます。それ以外の場合は、最初の不一致トークン以降のすべてが破棄され、新しい一時シーケンスでプロセスが繰り返されます。

一時トークンを生成する方法にはさまざまなオプションがあり、それぞれに異なるトレードオフがあります。複数のモデルをトレーニングしたり、単一の事前トレーニングされたモデルで複数のヘッドを微調整したりして、将来の複数のステップのマーカーを予測できます。あるいは、小さなモデルを一時的なモデルとして使用し、より大きな、より強力なモデルを検証ツールとして使用することもできます。

7.結論

この記事では、データ センターでも PC エッジでも、LLM の効率的な最適化とサービスを支援する最も一般的なソリューションの多くを概説します。これらのテクニックの多くは、NVIDIA TensorRT-LLM を通じて最適化され、提供されます。NVIDIA TensorRT-LLM は、TensorRT 深層学習コンパイラーと、最適化されたカーネル、前後処理ステップ、およびマルチ GPU/マルチノード通信プリミティブで構成されるオープン ソース ライブラリです。 NVIDIA の画期的なパフォーマンス GPU で。

おすすめ

転載: blog.csdn.net/wdnshadow/article/details/134766386