HUOXIU

大規模言語モデルの推論性能を最適化する7つの戦略

編集者注: 自然言語処理において大規模言語モデルが広く応用されるにつれ、実際の展開において推論速度をどのように向上させるかが重要な課題になっています。

本稿では、大規模言語モデルの推論速度を向上させるための7つの戦略を詳述します。具体的には、低精度計算、モデル量子化、アダプタのファインチューニング、モデルプルーニング、バッチ推論、マルチGPU並列処理、その他の推論最適化ツールの活用などが挙げられます。それぞれの手法には長所と短所があり、著者は具体的な例を用いてその有効性を示し、読者にこの分野における技術開発の現状を明確に理解してもらいます。


著者 | セルゲイ・サヴォフ

編纂者:岳陽

安定拡散法で生成された画像

小規模なスタートアップから大企業まで、あらゆる業種の企業が、最新の大規模言語モデルを活用し、自社製品や基盤ソフトウェアに統合したいと考えています。しかし、これらの企業は一般的に課題に直面しています。それは、大規模モデルの導入(推論)には膨大な計算リソースが必要となることです。

モデル推論の高速化は、コンピューティング リソースのコストを削減し、アプリケーションの応答性を向上させる方法を含め、開発者にとって大きな課題となっています。

「将来的には、大規模言語モデルの推論速度が 1% 向上するごとに、Google 検索エンジンの推論速度が 1% 向上するのと同等の経済的価値がもたらされるでしょう。」

— NVIDIAのAI科学者、ジム・ファン氏

LLM(大規模言語モデル)と関連する基盤ソフトウェアの開発は驚異的なスピードで進化しています[1]。モデルの圧縮や高速化のための新しい手法が毎週のように登場しています。このような急速な技術開発のペースの中で、理論的なレベルにとどまらず、トレンドに追いつき、どの手法が真に効果的かを理解することは、まさに挑戦的な課題です。

具体的なプロジェクトにおいてどのような改善を実施できるか、そしてそれらの改善がLLMモデルの推論速度をどのように向上させるかを理解するよう努めています。これにより、最新の技術動向をより深く把握し、具体的なプロジェクトに最適な最適化スキームを選択することができます。

01 「短い」要約

さまざまな大規模モデルの推論時間とメモリ消費量の比較、A100 GPU 40GB

この記事は少し長いですが、要点は次のとおりです。

1.精度を下げる: float16またはbfloat16を使用します。これにより、モデルの実行速度が約20%向上し、メモリ消費量が2分の1に削減されます。

2. 8ビットまたは4ビットの量子化を使用する: 8ビットまたは4ビットのモデル量子化を使用すると、メモリ消費量を2~3倍削減できます。この方法は、メモリ容量が限られた小型デバイスで実行する必要があるモデルに最適です。注:量子化により、モデルの予測品質が低下します。

3.微調整のためのアダプタ(LoRA [2] 、QLoRA [3] )を使用すると、特定のデータに対するモデルの予測精度と性能を向上させることができます。これは、モデル量子化技術と組み合わせて使用​​すると効果的です。

4.テンソル並列処理を使用すると、複数の GPU 上での大規模モデルの推論を高速化できます。

5. 可能であれば、Text Generation Inference、DeepSpeed[4]、vLLM[5]などのLLM推論およびサービスライブラリを使用します。これらのライブラリには、テンソル並列処理、モデル量子化、受信リクエストの連続バッチ処理、最適化されたCUDAカーネルなど、様々な最適化手法が既に含まれています。

6.大規模モデルを本番環境にデプロイする前に、初期テストを実施してください。私は特定のライブラリを使用する際のバグ修正に多くの時間を費やしました。また、すべてのLLMが実用的な推論加速ソリューションを備えているわけではありません。

7.最終的なソリューションを評価することを忘れないでください。簡単なテストのためにデータセットを準備しておくのが最適です。

それでは、これらの点について詳しく議論していきましょう。

02この実験におけるモデル選択

本文中で言及した関連テストでは、テクノロジー・イノベーション・インスティテュート[7]がリリースした新しいオープンソースの大規模言語モデルであるFalcon[6]を選択しました。これはデコーダー機能のみを備えた自己回帰モデルで、70億パラメータ版と400億パラメータ版の2つのバージョンがあります。4000億パラメータ版は、AWS上で384基のGPUを使用して2ヶ月間学習されました。

LLM リーダーボードを開きます。

私たちのモデル理解に基づくと[8]、FalconのアーキテクチャはGPT-3やLLaMAと非常に似ていますが、マルチクエリアテンション(Shazeer 2019[9])を使用し、 RefinedWeb [10]コーパスをトレーニングデータセットとして選択する点が異なります(これがモデルの成功の鍵となる可能性があります[11])。

マルチクエリアテンションは、異なるアテンションヘッド間で同じキーと値のテンソルを共有することで効率を向上させます。以下はマルチヘッドアテンションブロックの概略図です。

マルチクエリに注意してください。 https://lightning.ai/pages/community/finetuning-falcon-efficiently/

03最適化されていないベンチマーク実験 Vanilla の使用

実験を完了するために、最新のオープンソースLLMの設定可能な実装を含むLit-GPTライブラリ[12]を使用しました。このライブラリはLightning Fabric [13]を搭載しています。ハードウェア構成としては、40GBのビデオメモリを搭載したA100 GPUを使用しました。

実験は、モデルの重みをダウンロードし、lit-gpt形式に変換することから始まります。これは簡単で、次のスクリプトを実行するだけです。

 Python スクリプト/download.py --repo_id tiiuae/falcon-7b
Python スクリプト/convert_hf_checkpoint.py --checkpoint_dir チェックポイント/tiiuae/falcon-7b

モデルを実行するには、次のプログラムを実行するだけです。

 python generate/base.py \
--prompt "私はとても速いので、
--checkpoint_dir チェックポイント/tiiuae/falcon-7b \
--max_new_tokens 50
--precision "32-true"
# 推論時間: 合計 1.47 秒、33.92 トークン/秒
# 使用メモリ: 28.95 GB

04 LLM推論加速手法

3.1 16ビット精度を使用する

GPUを用いてディープニューラルネットワークを学習する場合、通常は32ビット浮動小数点演算を使用します。これは最高精度よりも低い精度です(実際、PyTorchはデフォルトで32ビット浮動小数点数を使用しています)。浮動小数点表現では、数値は符号、指数、仮数(または仮数)の3つの部分で構成されます。

単精度浮動小数点演算形式[14]

一般的に、精度が高いほど正確性が高くなり、計算中にエラーが蓄積される可能性が低くなります。しかし、モデルの学習速度を上げたい場合は、精度を例えば16ビットに下げることが可能です。これにはいくつかの利点があります。

1. GPU メモリ使用量を削減: 32 ビット精度では 16 ビット精度の 2 倍の GPU メモリが必要となり、精度を下げることで GPU メモリ リソースをより効率的に使用できるようになります。

2.計算能力と速度の向上: 精度の低いテンソルの演算では必要なビデオメモリが少なくなるため、GPU は計算をより高速に実行でき、モデルのトレーニング速度が向上します。

 Lit-GPT は Fabric ライブラリを使用するため、わずか数行のコードで精度を変更できます。
Python 生成/base.py \
--prompt "私はとても速いので、
--checkpoint_dir チェックポイント/tiiuae/falcon-7b \
--max_new_tokens 50
--precision "16-true"
# 推論時間: 合計 1.19 秒、42.03 トークン/秒
# 使用メモリ: 14.50 GB

3.2 混合精度トレーニング

混合精度学習は、GPUでの学習速度を大幅に向上させることができる重要な手法です。この手法では、すべてのパラメータと演算を16ビット浮動小数点数に変換するのではなく、学習中に32ビットと16ビットの演算を切り替えます。そのため、「混合」精度と呼ばれています。

混合精度法 [15]

この方法により、ニューラル ネットワークの精度と安定性を維持しながら効率的なトレーニングが可能になります。

 Python 生成/base.py \
--prompt "私はとても速いので、
--checkpoint_dir チェックポイント/tiiuae/falcon-7b \
--max_new_tokens 50
--精度「16混合」
# 推論 1 の時間: 合計 2.82 秒、17.70 トークン/秒
# 使用メモリ: 42.84 GB

3.3 16ビットブレイン浮動小数点

Bfloat16は、Googleが提唱する浮動小数点形式であり、「Brain Floating Point Format」と呼ばれています。これは、Google傘下の人工知能研究グループであるGoogle Brain[16]が発祥です。Bfloat16の詳細については、こちら[17]をご覧ください。

Bfloat16 演算。

Googleは、機械学習およびディープラーニングアプリケーション、特にTensor Processing Unit(TPU)向けにこの形式を開発しました。bfloat16は元々TPU向けに開発されましたが、現在では一部のNVIDIA GPUもこの浮動小数点形式をサポートしています。

 python -c "torchをインポート; print(torch.cuda.is_bf16_supported())"

bfloat16 を使用する必要がある場合は、次のコマンドを実行できます。

 Python 生成/base.py \
--prompt "私はとても速いので、
--checkpoint_dir チェックポイント/tiiuae/falcon-7b \
--max_new_tokens 50
--precision "bf16-true
# 推論時間: 合計 1.18 秒、42.47 トークン/秒
# 使用メモリ: 14.50 GB

次のグラフは上記の結果をまとめたものです。

異なる精度タイプの推論速度とメモリ消費量の比較

05モデルの量子化

推論中のモデル性能をさらに向上させたい場合は、浮動小数点精度を低くするだけでなく、量子化技術も使用できます。量子化は、モデルの重みを浮動小数点数から8ビット整数(あるいは4ビット整数)などの低ビット整数表現に変換します。量子化技術をディープニューラルネットワークに適用する方法は、一般的に2つあります。

1.学習後量子化(PTQ) :まずモデルを収束するまで学習させ、その後、それ以上の学習を行わずに重みを低い精度に変換します。このプロセスは、通常、モデル学習よりもはるかに低コストで実装できます。

2.量子化を考慮した学習 (QAT) : 量子化は事前学習時または更なる微調整時に適用されます。QATはパフォーマンスが向上する可能性がありますが、より多くの計算リソースと代表的な学習データを必要とします。既存モデルの推論を高速化したい場合は、学習後に量子化を行う必要があります。学習後の様々な量子化手法の詳細については、[18]をご覧ください。

注:最近の研究論文「SmoothQuant: 大規模言語モデルのための正確かつ効率的な学習後量子化」[19]では、すべての量子化手法が大規模言語モデル(LLM)に適しているわけではないことが指摘されています。したがって、量子化手法の選択は慎重に検討する必要があります。個人的には、LLAMAとFalconで使用されている量子化手法について解説している論文「SpQR: ニアロスレスLLM重み圧縮のためのスパース量子化表現」[20]を読むことをお勧めします。

異なる量子化手法を用いたモデルの精度低下の程度とパラメータ数の関係。出典:SmoothQuant:「大規模言語モデルのための正確かつ効率的な学習後量子化」

Falcon モデルはまだ 4 ビットおよび 8 ビットの整数精度を実現していないため、Lit-LLaMA を使用して LLaMA 7B の例を示します。

 Python generate.py \
--prompt "私はとても速いので、
--quantize llm.int8
# 推論時間: 合計 2.01 秒、24.83 トークン/秒
# 使用メモリ: 13.54 GB

06アダプタを使った微調整

微調整は最終的なモデル推論プロセスを高速化する直接的な方法ではないかもしれませんが、パフォーマンスを最適化するためにいくつかの手法を使用できます。

1.事前学習と量子化:まず、モデルはドメイン固有の問題で事前学習され、その後量子化されます。モデルの量子化は通常、モデルの品質をわずかに低下させますが、初期の事前学習によってこの問題をある程度軽減することができます。

2.小型アダプター:別のアプローチとして、異なるタスク向けに小型アダプターを導入する方法があります。アダプターは、既存のモデルレイヤーにコンパクトな追加レイヤーを追加し、そのレイヤーのみで学習することで機能します。これらのアダプターレイヤーは軽量なパラメータを持つため、モデルは迅速に適応し、学習することができます。

これらの方法を組み合わせることで、モデルのパフォーマンスを向上させることができます。

LLMのためのアダプタベースの知識注入アーキテクチャ[21]

アダプタの分野では、LLaMAアダプタ(v1[22]、v2[23])、LoRa、QLoRaなど、いくつかの亜種が登場しています。その中でも、 Low-Rank Adaptation(LoRA) [24]が最も際立っています。LoRAは、LLMの各層に少数の学習可能なパラメータ(アダプタ)を導入し、同時にすべての元のパラメータを固定します。この手法は、アダプタの重みの更新のみを必要とするため、微調整プロセスを簡素化し、メモリ消費を大幅に削減します。

QLoRA[25]メソッドは、LoRAにモデル量子化技術やその他の最適化を追加し、Google Colabインスタンスでモデルを微調整する方法を完全に変えました![26]

アダプタアーキテクチャ[27]

LLMのファインチューニングは、時間と計算能力を含む多くのリソースを必要とする場合があります。例えば、 8基のA100 GPUを使用したFalcon-7Bのファインチューニングには約30分かかりますが、1基のGPUを使用した場合は約3時間かかります。さらに、より良いファインチューニング結果を得るには、事前にデータセットを準備する必要があります。私は個人的にモデルのファインチューニングを実行したことはありませんが、以下のコマンドを実行することで開始できます(詳細はこちら[28]を参照)。

 Python Finetune/adapter_v2.py \
--data_dir データ/アルパカ \
--checkpoint_dir チェックポイント/tiiuae/falcon-7b \
--out_dir out/アダプタ/alpaca

詳細をより深く理解するには、以下をお読みになることをお勧めします。

  • 大規模言語モデルのパラメータ効率の良いファインチューニングの理解:プレフィックスチューニングからLLaMAアダプタまで[29]

  • ビットアンドバイト、4ビット量子化、QLoRAによりLLMがさらにアクセスしやすくなる[30]

  • LoRAとアダプタを使用してFalcon LLMをより効率的に微調整する - Lightning AI[31]

  • Colabノートブックで4bitとPEFTを使用してGuanacoデータセットでFalcon-7Bを微調整する[32]

07モデルの剪定

ネットワーク プルーニングは、モデルの容量を維持しながら、重要でないモデルの重みまたは接続を削除することでモデルのサイズを縮小します。

もう一つの革新的なアプローチであるLLM-Pruner[33]は、勾配情報に基づいて重要でない結合構造を選択的に削除し、構造的枝刈りを適用することで大規模言語モデルの機能性をほぼ維持することができます。著者らは、圧縮モデルがゼロショット分類と生成において良好な性能を示すことを実証しています。

(翻訳者注:LLM-Pruner は、パラメータの勾配に基づいてモデルの重要度を決定し、重要でない構造部分を削除することでモデルを圧縮します。削除する部分の選択は、パラメータの勾配の大きさに基づいて行われます。)

LLM-Prunerのイラスト

LLM-Pruner論文の著者らは関連コードを公開したが、サポートしているのはLLaMA-7B[34]とVicuna-7B[35]という2つの大規模言語モデルのみである。

もう一つの興味深い枝刈り手法はWanda[36]です(これは重みと活性化に基づいて枝刈りを行います)。この手法は、重みと各出力に対応する入力活性化の積に基づいて重みを枝刈りします。

重みの大きさのみに基づく振幅プルーニングと比較して、Wandaのプルーニング法は各出力に基づいており、重みの大きさに入力活性化値のノルムを乗じて重みを削除します[36]。

注目すべきは、Wandaは再学習や重みの更新を必要とせず、枝刈りされたLLMをそのまま使用できることです。さらに、WandaはLLMを元のサイズの50%に枝刈りすることができます。

08バッチ推論

GPUは超並列コンピューティングアーキテクチャとして知られています。A100[37]では、モデルの計算速度は毎秒テラフロップス単位で測定されますが、H100[38]などのGPUでは、毎秒ペタフロップスに達することもあります。LLMは膨大な計算能力を備えていますが、GPUチップのメモリ帯域幅の大部分がモデルパラメータの読み込みに使用されるため、その潜在能力を十分に発揮することが難しい場合が多くあります。

効果的な解決策の一つは、バッチ処理の利用です。入力シーケンスごとに新しいモデルパラメータを読み込む代わりに、バッチ処理ではモデルパラメータを一度だけ読み込み、複数の入力シーケンスの処理に使用します。この最適化戦略は、チップのメモリ帯域幅を効率的に利用することで、計算効率とスループットを向上させ、LLM推論のコスト効率を向上させます。バッチ処理を採用することで、LLM全体のパフォーマンスを大幅に向上させることができます。

最近提案されたもう一つの最適化手法は、連続バッチ処理です。Orcaは反復レベルのスケジューリングを実装しており、バッチ内の各シーケンスの生成が完了するまで待つ必要がありません。代わりに、各反復に基づいてバッチサイズを決定します。その結果、バッチ内の1つのシーケンスが生成されるとすぐに新しいシーケンスを挿入できるため、静的バッチ処理よりも高いGPU使用率を実現できます。

7つのシーケンスを連続バッチ処理で処理しました。左側は1回の反復処理後のバッチ処理結果、右側は複数回の反復処理後のバッチ処理結果を示しています。

このアルゴリズムは次のフレームワークで使用できます。

  1. テキスト生成推論[39]—テキスト生成推論のためのサーバー側アプリケーション。

  2. vLLM[40] — LLMの推論およびサービスエンジン。

慎重に評価した結果、vLLM を選択しました。vLLMは、アテンション キーと値を効果的に管理する新しいアテンション アルゴリズムである PagedAttention を使用します。モデル アーキテクチャに変更を加えなくても、そのスループットは HuggingFace Transformers より最大 24 倍高くなります。

vLLMは、HuggingFace Transformers (HF) の14~24倍、HuggingFace Text Generation Inference (TGI) の2.2~2.5倍のスループットを誇ります。出典: https://vllm.ai/

vLLMはFalconをサポートできないことを考慮して[41]、LLaMA-7Bに切り替えることにしました。

 vllmからLLMをインポートし、SamplingParams
プロンプト = [
「私はとても速いので、
「フランスの首都は」
「AIの未来は」
]
サンプリングパラメータ = サンプリングパラメータ(温度=0.8、top_p=0​​.95)
llm = LLM(モデル="ハギラマ/ラマ-7b")
出力 = llm.generate(プロンプト、サンプリングパラメータ)
出力内の出力の場合:
プロンプト = 出力.プロンプト
生成されたテキスト = output.outputs[0].text
print(f"プロンプト: {prompt!r}, 生成されたテキスト: {generated_text!r}")
# 私はとても速いので、2時間で世界を一周できます。最初の目的地は東南アジアです
# フランスの首都は世界で最も美しい都市の一つです。そして、それは周知の事実です。
# AIの未来は未来にある\nこれは悲観的な結論のように聞こえるかもしれないが、

優れた実行速度に感銘を受けました。さらに、このフレームワークはシームレスなAPIサーバーのセットアップと迅速なデプロイメントを可能にします。サービスを開始するには、以下のコマンドを実行してください。

 python -m vllm.entrypoints.api_server --model huggyllama/llama-7b

次に、次のコードを使用して機能を確認できます。

時間 curl http://localhost:8000/generate \
-d '{
「プロンプト」:「私はとても速いので、
「温度」: 0,
"use_beam_search": 真、
"n": 4,
}'
# 🚀 実数 0分0.277秒
# 私はとても速いので、ストーリー 3 を読み終えて、開始前に戻ることができます。
# 私はとても速いので、昼食のために戻ってくるのに地球を一周できます。
# 私はとても速いので、地球上で昼食までに終わらせることができます。\n私はとても速いです
# 私はとても速いので、世界中を走り回って自分の足でスタートすることができます。

バッチ推論のより詳細な評価とベンチマークについては、ここ[42]をご覧ください。

09複数のGPUを使用する

完全シャーディングデータ並列(FSDP)分散戦略を使用して、複数のGPUデバイスを推論に活用することもできます。複数のGPUデバイスを使用することで推論プロセスが高速化されるわけではありませんが、モデルを複数のデバイスに分割することで、単一のGPUでは実行できないモデルを実行できるようになることを理解することが重要です。

例えば、Falcon-40Bモデルを1台のデバイスで動作させるには約80GBのGPUメモリが必要です。Lit-GPTを使用し、パラメータをわずかに調整した上で、2枚のA6000カード(各48GB)で動作させた場合、以下のようになります。

 python generate/base.py \
--checkpoint_dir チェックポイント/tiiuae/falcon-40b \
--strategy fsdp \
--デバイス 2 \
--プロンプト「私はとても速いので、できます」
# 推論時間: 合計 83.40 秒、0.60 トークン/秒
# 使用メモリ: 46.10 GB

これにより、46 GB のメモリが消費され、1 秒あたり 0.60 トークンの速度で実行されます。

フルシャードデータ並列処理を使用する前と使用後のパフォーマンス比較。

あるいは、vLLM を使用することもできます。これは、tensor_parallel_size を 2 に設定するだけで、はるかに高速にテキストを生成します。

プロンプト = [
「私はとても速いので、
「フランスの首都は」
「AIの未来は」
]
llm = LLM(モデル="huggyllama/llama-30b", テンソルパラレルサイズ=2)
出力 = llm.generate(プロンプト、サンプリングパラメータ)
# 🚀 たった0.140秒しかかかりません!
# 私はとても速いので、朝食を食べる前に過去に戻って朝食を食べることができます!
# AIの未来はあなた次第です。

10.追加セクション: LLM モデルサービスの展開

vLLMはFalconをサポートしていないため、テキスト生成推論[39]を使用してモデルを簡単に展開する方法を示すことにしました。

テキスト生成推論アーキテクチャ

フレームワーク作者の推奨使用法に従うには、提供されているコマンドを使用して、Dockerコンテナ内でアプリケーションを実行することをお勧めします。Dockerコンテナを実行するコマンドは次のとおりです。

 docker run --gpus all --shm-size 1g -p 8080:80 \
-v $PWD/data:/data ghcr.io/huggingface/テキスト生成推論:0.8 \
--model-id tiiuae/falcon-40b --num-shard 1 --quantize ビットとバイト

Falcon-7Bはテンソル並列処理をサポートしていないことに注意してください[43]。したがって、適切に機能するには、パラメータnum_shardを1に設定する必要があります。

私の経験では、このプロセスはDockerイメージのダウンロードに約2分、スケールのダウンロードに約30秒かかります。その後、スケールを.bin形式から.safetensors形式に変換するのに約20秒かかります。最後に、最終モデルのダウンロードには約1分かかります。

次のコマンドを使用して、API の動作を確認できます。

時間 curl http://localhost:8080/generate \
-X ポスト \
-d '{"inputs":"私はとても速いので、","parameters":{"max_new_tokens":50}}' \
-H 'コンテンツタイプ: application/json'
# 実数 0分3秒148秒
# 私はとても速いので、同時に 2 つのことができます。

LLM推論用の他の代替ライブラリ:

1. Accelerate [44]:このライブラリは、モデルのワークロードの一部をCPUにオフロードすることを可能にします。モデル全体がGPUで動作するように設計されている場合でも、一部の計算タスクをオフロードすることで推論サービスのスループットを最適化できます。

2. DeepSpeed Inference [45]:このライブラリは、(a) モデルがGPU上での実行に適しており、(b) DeepSpeedライブラリがモデルカーネルをサポートしている場合、Transformerベースのモデルをより効率的に処理できます。レイテンシの問題に重点を置く必要がある場合、このソリューションは選択肢となります。

3. DeepSpeed MII [46]:モデル推論のためのGRPCターミナルノードを迅速にセットアップできるライブラリです。ZeRO-InferenceまたはDeepSpeed Inferenceテクノロジーを選択できます。

4. OpenLLM [47]:大規模言語モデル(LLM)を本番環境で実行するためのオープンプラットフォームです。LLMは簡単にチューニング、デプロイ、サービス提供、監視が可能です。

5. Aviary [48]:これは、複数のLLMモデルに対してセルフホスト型サービスを効果的に簡素化し、有効にすることができる新しいオープンソースプロジェクトです。

詳細については、ここ[49]をご覧ください。

11要約

LLM推論加速の分野は複雑で、まだ初期段階にあります。この記事を執筆する中で、最近開発された多くの手法を発見しました。その中には非常に有望なものもいくつかあります(これらの手法はすべて、ここ1~2ヶ月以内に登場したものです)。

ただし、すべての推論高速化手法が確実に機能するわけではないことに注意することが重要です。一部の手法はモデルの品質を低下させる可能性があります。したがって、推論高速化の提案をすべて盲目的に受け入れて適用するのは賢明ではなく、慎重に検討する必要があります。常に注意を払い、高速化されたモデルの品質を管理する必要があります。

理想的には、ソフトウェアの最適化とモデル アーキテクチャのバランスをとることが、LLM 推論の効率的な加速を実現するための鍵となります。

終わり