著者 | ピエール・リアンハート 編纂者:岳陽 01 はじめにこのブログシリーズでは、LLM推論の様々な側面と、実際に発生する可能性のある課題について、読者の皆様に深く掘り下げて解説していきます。本シリーズで扱うLLM推論は、デコーダーのみを含むTransformerモデルを用いたトークン生成を指します。多くの課題とそれに関連する解決策は、この特定のアーキテクチャとユースケースに起因しているからです。本シリーズはデコーダーモデルに焦点を当てていますが、本シリーズで得られる貴重な知見の一部は、エンコーダーモデルの推論プロセスを理解し、最適化するためにも活用できると考えています。 Transformerアーキテクチャと、有名な論文「Attention Is All You Need」[1]で説明されているScaled Dot Product Attention(SDPA)メカニズムについては、既に基本的な理解があることを前提としています。ただし、この記事を読むために、Attentionメカニズムの背後にある原理を深く理解する必要はありません。 このブログ シリーズを終える頃には、読者はキー値 (KV) キャッシュやメモリ帯域幅の制限などの LLM 推論関連の用語を理解し、さまざまな推論最適化手法 (モデルの量子化、融合カーネル、モデル アーキテクチャの変更など) と構成手法 (バッチ サイズ、GPU の選択など) を理解し、最後にそれらをレイテンシ、スループット、コストなどの主要なパフォーマンス指標に関連付けることができるようになっているはずです。 このシリーズの目的は、読者がコンテンツを理解することで洞察力のある思考を養い、LLMサービスの設定と最適化を行う際に、迅速かつ情報に基づいた意思決定を行えるようにすることです。このシリーズの他の記事と同様に、LLMを初めてサーバーに導入する読者に必要な情報とガイダンスを提供したいと考えています。 それでは、このシリーズの概要をご紹介します。 まず、Transformerデコーダーを用いたトークン生成には、キューメッセージの処理と複数の自己回帰ステップという2つのステップが含まれることを理解する必要があります。これらの2つのステップは、ハードウェア利用特性が明確に異なるため、このシリーズを通して詳細に検討していきます。 次に、自己回帰ステップで最初に行われる非常に一般的な最適化であるキーバリュー(KV)キャッシュについて紹介します。KVキャッシュは自己回帰フェーズ全体に影響を与える重要な入力となるため、特に注目すべき点です。後述するように、 KVキャッシュは単なる便宜的なものではなく、多くの問題を引き起こします。以下の記事では、これらの課題とその緩和策についてより深く掘り下げ、このトピックに特化したセクションを設けます。 KVキャッシングを完全に理解することで、Transformerを推論実行する際に、Transformerモデルがハードウェアリソースをどのように(十分に)活用しているかをより深く理解できるようになります。この段階では、演算強度という重要な概念、つまり「ルーフラインモデル」と呼ばれるメンタルモデルを導入する必要があります。ルーフラインモデルは、計算負荷の高いタスクのパフォーマンス限界を評価するために使用される特定のメンタルモデルで、ハードウェアの限界を直感的に理解し、最適化を導くためにグラフィカルに表示されることが多いものです。次に、これをピークFLOPSやメモリ帯域幅などの主要なハードウェア特性、そしてレイテンシ、スループット、コストなどの主要なパフォーマンス指標と関連付けます。この知識をTransformer推論に適用し、ハードウェアをより有効に活用し、パフォーマンス指標を向上させる方法を理解するための重要な洞察をまとめます。この段階でこれらの基礎を理解することで、さまざまなパフォーマンス最適化戦略の背後にある真の動機をより深く理解し、実用的なアプリケーションのためのより深いガイダンスを得ることができます。 モデル量子化は昨年最も注目を集めた最適化戦略の一つであり、大幅なパフォーマンス向上をもたらしました。モデル量子化自体は複数の記事で構成する価値がありますが、ここでは読者の皆様にしっかりとした基礎知識を提供し、モデル量子化アルゴリズムがどのような側面で役立ち、どのような側面で役立たないかを明確にするため、1つの記事でのみ紹介することにします。 最後に、これらの現在のLLMサービスフレームワークがどのように機能するかを説明する必要があります。残念ながら、モデル自体を最適化するだけでは、LLM推論プロセスで最適なパフォーマンスを実現することはできません。実際には、モデルサーバーは、受信リクエストとハードウェアリソースを効果的に管理することで、エンドツーエンドの優れたパフォーマンスを確保する上で重要な役割を果たします。この記事が読者の皆様にとって、LLMをより適切に導入するための有益な情報を提供できれば幸いです。 このブログシリーズのコンテンツ プランは次のとおりです。
雑談はもう十分です、始めましょう! 02 LLMが回答する前に行う2つのステップこのセクションでは、読者の皆様のためのウォームアップとして、Transformerのアーキテクチャと、Transformerベースのデコーダーを用いたテキスト生成の基本について概説します。このブログシリーズを理解し、習得するには、一貫した技術用語体系を確立することが重要です。個人的によく使用する技術用語は太字で強調表示します。次に、テキスト生成の2つの段階、すなわち開始段階と生成(またはデコード)段階について見ていきます。 まず、Transformerについて確認しましょう。説明を簡潔にするため、一度に処理されるシーケンスは1つだけ(つまり、バッチサイズは1)と仮定します。下の図は、オリジナルのTransformerアーキテクチャに基づいたデコーダー(図1)の主な階層構造を示しています。このデコーダーは、入力トークンシーケンスから出力トークンを生成するために使用されます。 図1 - Transformerデコーダーのモデル概要 デコーダー自体はトークンではなく、ロジット(語彙数と同じ数)を出力することに注意してください。(訳者注:ロジットとは、語彙数と同じ次元を持つ数値ベクトルで、各トークンの確率スコアを表します。)ちなみに、ロジットを出力する最後の層は、言語モデルヘッドまたはLMヘッドと呼ばれることがよくあります。テキスト生成において、ロジットからトークンを抽出するプロセスは、探索戦略、生成戦略、またはデコード戦略と呼ばれるヒューリスティックなアプローチによって実現されます。一般的なデコード戦略には、以下のものがあります。
簡潔にするために、デコード戦略はモデルの一部であると仮定します(図2)。このメンタルモデルは、大規模な言語モデルサービスの導入、実行、提供のためのソリューション全体において、実は非常に有用です。トークンのシーケンスを入力として受け取り、対応する出力トークンを返すこのエンティティは、通常、実行エンジンまたは推論エンジンと呼ばれます。 図2 - Transformerデコーダーモデルの簡略図 では、複数のトークンを生成するにはどうすればよいでしょうか。Transformer ベースのデコーダーを使用して入力テキストシーケンス(プロンプトと呼ばれることもあります)からテキストを生成(入力テキストの拡張または補足とも呼ばれます)するには、基本的に次の手順に従います。
図3 - 単語分割手順の概略図 3. 単語分割後のプロンプトをニューラル ネットワークに入力して、最初の拡張トークンを生成します。 この段階はしばしば開始段階と呼ばれます。次の記事では、この段階がプレフィル段階とも呼ばれることを説明します。 4. 生成されたトークンを入力トークンシーケンスに追加し、それを新しい入力として使用して、拡張テキストの2番目のトークンを生成します。その後、停止シーケンス(例えば、単一のシーケンス終了(EOS)トークン)が生成されるか、設定された最大シーケンス長に達するまで、このプロセスを繰り返します(図4)。 このフェーズは複数のステップで構成されており、生成フェーズ、デコード フェーズ、自己回帰フェーズ、または増分フェーズと呼ばれることもあります。 ステップ 3 と 4 は下の図に示されています (図 4)。 図4 - トークン生成プロセスの起動とデコードフェーズ 5. 完成したトークンはGPUからCPUに転送され、デトークン化(注:「デトークン化」とは、モデルによって生成されたトークンシーケンスを元のテキストまたは文に戻すプロセスを指します。これには、トークン間のスペースの削除、句読点の追加、略語の復元など、生成されたテキストの自然言語形式を復元することが含まれます)されて、生成テキストが得られます(図5)。 図5 - トークン解除手順 注:推論の遅延を減らすために最近登場した、投機的サンプリング[3]や先読みデコード[4]などのより高度な技術は、上記の単純なアルゴリズムに完全に従っていません。 この時点で、あなたはがっかりしたり、混乱したり、あるいはその両方を感じたりするかもしれません。「スタートアップフェーズとデコードフェーズの違いは何だろう?」と疑問に思うかもしれません。どうやら、これは単なる人為的な区別に過ぎないようです。スタートアップフェーズは、whileループの初期化ステップのように感じられ、どちらのフェーズでも行うことは本質的に同じです。つまり、各イテレーションでトークンのシーケンスを前方に渡し、そのたびにシーケンスを1トークンずつ増やしていくのです。 おっしゃる通りです。現時点では、ハードウェア上での計算方法に関わらず、2つのステージに実質的な違いはありません。つまり、どちらのステージもこの点では特に特別なものではありません。しかし、次の記事で説明するように、この設定では多くの冗長な計算が行われるため、多くの場合非効率になります。この問題を軽減する重要な方法は、再コンパイルしたくないものをキャッシュすることです。この最適化はKVキャッシュと呼ばれ、私がこれまで示唆してきた2つのステージの重要な違いを生み出します。それでは、次の記事でお会いしましょう! 読んでくれてありがとう! 終わり 参考文献
|