vLLM、Tenstorrentアクセラレータ対応プラグイン「TT Plugin」を公開
本文の状態
日本語全文を表示中
詳細モードで約28分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
vLLM Blog
vLLM は Tenstorrent アクセラレータを標準プラグイン機構で統合し、GPU と異なるアーキテクチャ特性を持つハードウェア上で LLM サービングを実現する vLLM TT Plugin を公開した。
AI深層分析を開く2026年9月7日 19:30
AI深層分析
キーポイント
vLLM TT Plugin の公開と仕組み
Tenstorrent アクセラレータを vLLM に統合する標準的なアウトオブツリープラグインが公開され、ttnn が利用可能になると自動的にハードウェアが検出・登録される。
GPU とは異なるアーキテクチャへの対応
Tenstorrent デバイスは GPU と外観や動作原理が大きく異なり、このプラグインによりフェーズ制約スケジューラや独自のデータ並列トポロジをコア外で実装可能となった。
対応モデルアーキテクチャの拡大
Llama 3.1〜3.3、Qwen 2.5/3/3.5/3.6、Mistral、Gemma 3/4、DeepSeek V3 など主要な LLM アーキテクチャが TT プレフィックス付きのクラスとしてサポートされる。
API 互換性の維持
バックエンドの変更にもかかわらず、OpenAI 互換 API やリクエスト形式、クライアントコードは変更されず、既存の運用フローを維持できる。
アーキテクチャベースのモデルマッピング
各クラスは vLLM に向けられたジェネレーターとして TT-Metal に実装され、名前は登録のみで TTNN の実装が解決される。1 つのエントリで複数のリリースをカバーし、マルチモーダル対応も含まれる。
重要な引用
Tenstorrent device does not look much like a GPU
express those differences - a phase-constrained scheduler, a different data-parallel topology, a sampling path that partly lives on device - entirely outside vLLM core
The plugin carries no model code - it registers the names, and tt-metal provides what they resolve to
The plugin carries no model code - it registers the names, and tt-metal provides what they resolve to.
編集コメントを表示
編集コメント
Tenstorrent のような非 GPU アーキテクチャを vLLM の標準プラグインとして統合した点は、ハードウェア多様化時代の LLM インフラにおいて極めて重要なステップである。アーキテクチャ名ベースのマッチングにより、モデル実装とフレームワーク側の責任範囲が明確に分離された設計は、今後の拡張性にも寄与するだろう。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
本日、**vLLM TT Plugin** をご紹介します。このプラグインは、標準的なアウト・オブ・ツリー(out-of-tree)プラットフォームプラグイン機構を通じて、Tenstorrent アクセラレータを vLLM に統合します。
vLLM と併せてインストールすれば、TT-Metal の ttnn がインポート可能になった時点で、Tenstorrent ハードウェアが自動的に検出され、vLLM プラットフォームとして登録されます。サービングのインターフェースは変更されません。OpenAI 互換 API も、リクエスト形式も、クライアントコードもそのままです。
このプロジェクトで特に興味深いのは、バックエンドが存在すること自体ではなく、Tenstorrent デバイスが GPU とは大きく異なる点に対し、vLLM のプラグインインタフェースが十分に汎用的であったことです。これにより、位相制約付きスケジューラやデータ並列トポロジーの違い、デバイス上で一部実行されるサンプリングパスといった差異を、vLLM コアの外側で表現することが可能になりました。
サポート対象モデル
このプラグインは、TT プレフィックスを持つ規約に従って Tenstorrent ベースのアーキテクチャを登録します。そのため、チェックポイントは名前ではなく、自身が宣言するアーキテクチャに基づいて読み込まれます:
| モデルファミリー | アーキテクチャ |
|---|---|
| Llama 3.1 / 3.2 / 3.3 | TTLlamaForCausalLM |
| Llama 3.2 Vision | TTMllamaForConditionalGeneration |
| Qwen 2.5 / Qwen 3 | TTQwen2ForCausalLM, TTQwen3ForConditionalLM (原文の技術表記: TTQwen3ForCausalLM) |
| Qwen 3.5 / Qwen 3.6 | TTQwen3_5ForConditionalGeneration |
| Qwen 2.5-VL / Qwen 3-VL | TTQwen2_5_VLForConditionalGeneration, TTQwen3VLForConditionalGeneration |
| Mistral / Mistral 3 | TTMistralForCausalLM, TTMistral3ForConditionalGeneration |
| Gemma 3 | TTGemma3ForConditionalGeneration |
| Gemma 4 | TTGemma4ForCausalLM, TTGemma4ForConditionalGeneration, TTGemma4UnifiedForConditionalGeneration |
| DeepSeek V3 | TTDeepseekV3ForCausalLM |
| GPT-OSS 20B / 120B | TTGptOssForCausalLM |
これらのクラスは、ランタイム自体とともに TT-Metal に含まれています。各クラスは、モデルの手書き TTNN 実装をラップした vLLM 向けのジェネレーターです。プラグイン側にモデルコードは含まれておらず、名前を登録するだけで、tt-metal がその解決先を提供します。
アーキテクチャベースでマッチングが行われるため、1 つのエントリが複数のリリースをカバーできます。例えば TTQwen3_5ForConditionalGeneration は、Qwen/Qwen3.6-27B をサーブするために使用されます。
新しいバックエンドは長期間テキスト専用になりがちであるため、マルチモーダル対応の重要性に言及しておきます。現在、Llama 3.2 Vision、Qwen-VL、Qwen 3.6、Mistral 3、Gemma 3 はすべてこのプラグインを通じてサーブ可能です。
モデルはプラグインに組み込む必要はありません。EXTRA_MODELS_DIR 環境変数で、vllm_metadata.json とアダプタークラスをそれぞれ含むバンドルフォルダが格納されたディレクトリを指定することで、起動時に TT<HFArch> という名前でアーキテクチャが登録されます。
配布ツールを使えば、ソースコードを編集することなくすぐに利用可能なモデルを配信できます。TT_VLLM_BUILTIN_MODELS=0 を設定すると、登録リストは提供されたものだけに絞り込まれます。
これで今日から利用可能な機能の概要はカバーできました。残りの部分では、その仕組みについて解説します。メッシュアーキテクチャが GPU 向けの配信スタックに課す設計上の制約と、それらを解決する過程で得られた知見です。
テンストロンハードウェア向けバックエンドが異なる理由
テンストロン(Tenstorrent)のハードウェア上で大規模言語モデル(LLM)を動作させる場合、従来の GPU ベースの実装とは根本的に異なるアプローチが必要となります。これは、アーキテクチャの違いや最適化の優先順位が異なるためです。
テンストロンは、AI 推論に特化した独自のプロセッサ設計を採用しており、メモリ階層や並列処理の仕組みが NVIDIA の GPU とは大きく異なります。そのため、vLLM のような既存のフレームワークをそのまま適用するのではなく、ハードウェア特性に合わせてバックエンドを再構築する必要があります。
この違いを理解することは、テンストロン環境で LLM を効率的に運用するための第一歩です。
Tenstorrent システムは、オンチップファブリックネットワークで接続されたコアとチップのメッシュです。n150 や n300 といった単一のカードも小規模なメッシュであり、QuietBox はより大規模な構成、Galaxy は 32 個の Wormhole チップを、ランタイムが直接設定するトポロジー(FABRIC_1D、FABRIC_2D、FABRIC_1D_RING)に配線したものです。プログラムはメッシュ形状に合わせてコンパイルされトレースされます。ファブリックによるチップ間でのデータ転送は、ホストから発行される集合呼び出しではなく、コンパイル済みプログラムの一部として実行されます。
このプラグインを通じて提供されるモデルは、2 チップ構成の n300 から 32 チップ構成の Galaxy に至るまで、Tenstorrent メッシュ向けに手書きで実装された TTNN の実装です。このシステム内では、GPU で用いられるのと同じ並列化戦略(チップ間でのテンソル並列処理や、サブメッシュ間でのデータ並列処理)が実行されます。ただし、これらは TTNN として記述され、ランタイムランクの設定ではなく、メッシュプログラムとしてコンパイルされる点が異なります。この手動チューニングこそが、トークンあたりのコスト効率を高める要因です。具体的な数値についてはここでは引用しませんが、最新のデータは tenstorrent.com や GitHub で確認できます。
図 1:チップ間並列処理の仕組み。GPU を模したスタックでは、ホストが各層で集合演算を発行し、並列処理はテンソル並列やパイプライン並列のランクとして実行時に選択されます。一方、Tenstorrent ではメッシュ全体が 1 つのプログラムとしてコンパイル・トレースされ、ファブリックがその内部でチップ間データを移動するため、ホストは 1 ステップごとにデータの送信と読み出しを 1 回ずつ行います。
この「メッシュ全体を 1 つのトレース済みプログラムとする」というコンパイルモデルが、その後のほぼすべての処理を決定づけています。
- 設定するテンソル並列やパイプライン並列のランクはありません。 Galaxy で 70B モデルを動かす場合、「TP=32 プロセス」という概念ではなく、32 チップのメッシュ向けにコンパイルされた単一のプログラムとして動作します。
MESH_DEVICE=TGは、--tensor-parallel-sizeの代わりに使用され、プラグインは-tpや-ppを無効として拒否します。
モデルとメッシュの組み合わせに最適な並列化手法は、モデルコード内に実装されます。
- 作業単位は、トレースされたステップ全体です。 デバイス実行は固定バッチ形状に対するキャプチャ済みトレースの再生が支配的となるため、均質で形状が安定したバッチは、不均質なバッチに比べて劇的にコストを抑えることができます。
サンプリングをデバイス上で行うことが可能です。メッシュプログラムがサンプリング処理を終端まで担えるため、トークンが選択された状態で戻ってくることも多く、ホスト側はロジット値を直接見る必要がありません。
これらはいずれも、GPU 形状の推論スタックに組み込まれた何らかの前提と矛盾する可能性があります。以下では、それらの課題をどのように解決したかを解説します。
フォークではなくプラグインとして実装
vLLM のハードウェアプラグイン機能は、2025 年 5 月に発表されました(詳細はこちら)。この機能の初期利用例として vllm-ascend や vllm-spyre が挙げられていますが、特に Spyre の取り組みから生まれた「プラグイン対応スケジューラ」の技術が、私たちのアプローチを可能にする基盤となっています。私たちはこの仕組みに大きく依存しています。
本プラグインは 2 つのエントリーポイントを登録します:
| エントリーポイントグループ | 名前 | ターゲット |
|---|---|---|
vllm.platform_plugins | tt | vllm_tt_plugin.entrypoints:platform_plugin |
vllm.general_plugins | tt_model_registry | vllm_tt_plugin.entrypoints:register |
platform_plugin() は、ttnn がインポート可能である場合にのみ TTPlatform を返すため、通常の CUDA 環境にパッケージをインストールしても、誤って Tenstorrent プラットフォームが選択されることはありません。
そこから、すべての処理は単一のハンドオフを通じて流れます。TTPlatform.check_and_update_config() は設定の検証を行い、モデルアーキテクチャを登録するとともに、vLLM の既存の拡張ポイントを通じて Tenstorrent 独自のランタイムクラスに差し替えます。
| vLLM 設定フィールド | TT 実装 |
|---|---|
parallel_config.worker_cls | vllm_tt_plugin.worker.TTWorker |
scheduler_config.scheduler_cls | vllm_tt_plugin.scheduler.TTScheduler または vllm_tt_plugin.lane_scheduler.TTLaneCoordinator |
デバイス固有のオプションは、新しい CLI フラグではなく、vLLM の汎用的な additional-config 名前空間を通じて設定されます。
--additional-config.tt.sample_on_device_mode all
--additional-config.tt.fabric_config FABRIC_1D_RINGTenstorrent に特有の機能は vLLM コアには含まれていません。これがバックエンドの実用性を決定する重要な要素です。この設計により、サポート体制が Tenstorrent のリリースサイクルではなく、vLLM 自体の更新頻度に追従します。その結果、開発者が本流から 3 ヶ月も遅れたフォーク版に置き去りになるという事態を防げます。
現在、当社は特定の vLLM リリースに対して検証を行っており、プラグインの API 表面が安定するにつれて、対応範囲を徐々に広げていく予定です。
フェーズ別スケジューリング:プレフィルのみまたはデコードのみステップ
アップストリームの vLLM V1 スケジューラはトークン予算ベースで設計されており、これは意図的なものです。リクエストには計算済みのトークンとターゲットとなるトークンがあり、各ステップでは予算の範囲内でさらに多くのトークン処理を割り当てます。
プレフィルとデコードが別々のモードとして存在しないことが、チャンク化されたプレフィルや進行状況が異なるバッチの自然な実装を可能にしています。
一方、Tenstorrent のパスはより制約が多く、各スケジューリングステップの結果は以下の 3 つのいずれかに収束します。
- prefill-only
- decode-only
- empty
混合されたプリフィルとデコードのバッチは存在しません。この制約の下では、チャンク化されたプリフィルがサポートされています。つまり、1 ステップあたりのトークン予算を超えるプロンプトは複数のプリフィルステップに分割され、その間にデコード専用ステップが挿入されます。これにより、進行中のリクエストは長いプリフィル処理中でも継続して進捗し、KV キャッシュの圧力も緩和されます。
デフォルトではプリフィル作業が優先的に割り当てられるため、その後でより大きなバッチによる効率的なデコードステップが実行されます。もしプリフィルを割り当てられるリクエストがない場合でも、デコードリクエストが動作している場合はそのステップはデコード専用となり、処理の継続と KV キャッシュ圧力の緩和が可能になります。
図 2:両方のスケジューリングモデルにおける同じ長いプロンプトの比較。アップストリームでは、このプロンプトは 4 つのチャンク化されたステップに分散され、他のリクエストのデコード作業もこれらのステップに混在します。一方、Tenstorrent では各ステップはプリフィル専用かデコード専用のどちらかに固定されます。つまり、プロンプトはプリフィル専用チャンクとして実行され、その間にデコード専用ステップが挿入されるため、各ステップは安定した形状を維持し、進行中のリクエストも継続して進捗します。
これは最も注目を集める設計選択の一つですが、この選択に伴うコストとメリットについて正確に理解しておく価値があります。
何をもたらすか。 追跡実行はバッチ形状の安定性を重視します。プリフェル(事前計算)またはデコード(推論生成)のいずれかに一貫したステップであれば、その形状に正確に対応する追跡を再生できますが、両者を混合するステップでは、追跡が存在しない形状が必要となるため対応できません。このフェーズ分離は Tenstorrent 独自の工夫ではありません。最大の GPU デプロイメントでも同様の選択を意図的に行っており、プリフェルとデコードを完全に独立したインスタンスで実行しています(非集約型サービング)。Tenstorrent のスケジューラーは、ファームウェア全体にまたがるインスタンス単位ではなく、1 つのエンジン内でステップ単位で同様の分離を適用します。
何がかからないか。 広義には連続バッチ処理は維持されます。リクエストは waiting(待機中)に入り、構造化出力の文法コンパイル中に skipped_waiting に一時保留されることがあります。他のリクエストがアクティブなままでも承認され、必要に応じてプリエンプション(中断)されて再度待機状態に戻り、それぞれ独立して完了します。制限はリクエストのライフサイクル全体ではなく、デバイスステップ内部でのみ適用されます。
コストがかかる要因として、インターリーブの粒度が「1 ステップ単位」であることが挙げられます。Upstream ではプリフェッチチャンクと進行中のデコードを同じステップに混合しますが、Tenstorrent のスケジューラは交互に切り替えるため、デコードリクエストは自身のステップ間の各プリフェッチチャンクの完了を待たなければなりません。また、モードの切り替えごとに、後述する非同期デコードのオーバーラップパイプラインが空転してしまいます。これらはハードウェアや vLLM に根本的な制限があるわけではなく、単にスケジューリングポリシーによるコストです。将来的には、混合形状のステップをキャプチャすることを妨げる要素はハードウェアにも vLLM にも存在しません。
Galaxy におけるシングルプロセス・レーンデータ並列性
これは vLLM の他の部分には見られない独自の機能であり、特にフィードバックを求めたい部分です。
Tenstorrent でサポートされている一部のモデル(TT_LLAMA_TEXT_VER=llama3_70b_galaxy を介した Llama 3.3 70B、TT_QWEN3_TEXT_VER=qwen3_32b_galaxy を通じた Qwen3-32B、および GPT-OSS)は、「シングル・エグゼキュート」ジェネレータによって提供されます。これは Galaxy メッシュ全体をまたぐ 1 つのプログラムであり、各ステップで一度だけ実行されます。第 2 のエンジンプロセスに割り当てるためのサブメッシュが存在しないため、標準的なマルチプロセス・データ並列性(各ランクに独自のデバイスを割り当てる方式)では分割する対象がありません。
しかしながら、これらのモデルは単一の重みと単一の実行を持つものの、4 つの独立したデータ並列 KV キャッシュを保持しています。それぞれが独自の DP サブメッシュ上に存在します。つまり、プロセスレベルで分割すべきものは何もない一方で、スケジューリング対象として独立して管理すべき要素が 4 つあるのです。
当初の実装では、vLLM の通常通り各 DP ランクに個別のプロセスを割り当てる方針でした。しかし、ランク同士がプリフィルとデコードのステップタイプについて調整を行う必要があること、そして実際にはメッシュの送信・読み出しが一つしかないことから、vLLM コア自体を大幅に変更する必要が生じました。これはハードウェアプラグインの仕組みの範囲を超えた変更です。
各ランクごとのスケジューラーは並列で実行されていましたが、ステップごとに発生する追加のプロセス間での散乱・集約(scatter/gather)のコストが、その並列化によって得られるメリットを上回ってしまいました。
より良い解決策は、並列処理を一つのエンジンプロセス「内部」に実装することです。
TTLaneCoordinator は、各レーンごとに独立した TTScheduler を1 つ所有しています。各レーンは、独自の待機キューと実行キューを持ち、それぞれの入場管理を行います。 (原文の技術表記: waiting、running)
意思決定、独自の KV キャッシュ管理機能、そして独自の
レーンローカルなブロックID空間です。新しいリクエストは、最も負荷の少ないレーンに割り当てられ、そのレーンにバインドされたままになります。
デバイスがすべてのレーンを同時に実行するため、コーディネーターは各ステップで 1 つの共有モードを選択する必要があります。
- いずれかのレーンがプリフェル(prefill)を受け入れられる場合、すべてのレーンがプリフェルステップを実行します。これは、単一スケジューラーの場合と同様に、デコードとインターリーブの間隔に制限されます。
- それ以外の場合は、すべてのレーンがデコードステップを実行します。
選択されたモードで処理すべき作業がないレーンは、マージされたバッチに対して空のスライスを寄与する。
コーディネーターは各レーンの SchedulerOutput オブジェクトをマージし、ワーカーが1つの統合されたデバイス入力を構築します。その後、ランナーはその結果を再びレーンごとに分割します。これらはすべて単一のプロセス内で完結しており、プロセスレベルの集合通信は一切行われません。これはまさに、マルチプロセス方式で失敗した原因となった散乱/集約(scatter/gather)のコストそのものです。
図3:同じ4つのデータ並列KVキャッシュを、2つの異なる方法でスケジューリングした様子。上段は私たちが放棄した設計です:1つのメッシュ送信と読み出ししか行わないにもかかわらず、各ステップごとに4つのエンジンプロセスが相互プロセス間の散乱/集約を通じて共有のプリフェッチまたはデコードモードについて合意形成を行います。下段が実際に採用された設計です:1つのエンジンプロセス、共有モードを決定するコーディネーター、レーンローカルのブロックIDを持つ4つの独立したスケジューラー、1つの統合されたデバイス入力、そして結果を再びレーンごとに分割します。
私たちは、ある微妙な点に気づくまで時間がかかりました。強制的なプリフェッチステップでゼロトークンしか受け入れられない場合(通常は KV 圧力によるもの)、かつ一部のレーンでデコード処理が進行中の場合、そのステップはデコードモードとして再試行されます。この再試行を行わないと、KV 圧力がコーディネーターを進捗なしのループに陥らせてしまいます。具体的には、「あるレーンがトークンの受け入れを望む」ためにプリフェッチが選択されるものの、「利用可能なブロックがない」ため何も受け入れられず、その結果としてブロックを解放するはずだったデコード処理が実行されないという悪循環です。
これらすべての仕組みに対するユーザー向けのインターフェースは、あえて地味なものです:
MESH_DEVICE=TG \
TT_LLAMA_TEXT_VER=llama3_70b_galaxy \
VLLM_RPC_TIMEOUT=900000 \
python examples/server_example_tt.py \
--model "meta-llama/Llama-3.3-70B-Instruct" \
--data_parallel_size 4 \
--max_num_seqs 8 \
--async-scheduling \
--additional-config.tt.dispatch_core_axis col \
--additional-config.tt.sample_on_device_mode all \
--additional-config.tt.fabric_config FABRIC_1D_RING \
--additional-config.tt.worker_l1_size 1344544 \
--additional-config.tt.trace_region_size 220000000--data_parallel_size 4 --max_num_seqs 8 を指定すると、32 の並行リクエストを処理する 4 つのインプロセス・レーン(各レーンに 8 リクエストずつ)が生成されます。ここで --max_num_seqs は、1 レーンあたりの容量を意味します。
ユーザーはこれまで通り既知のフラグを記述するだけでよく、バックエンドがモデルの実態に応じて最適なトポロジへ自動マッピングします。単一実行 Galaxy モデルの場合はインプロセス・レーンを使用し、それ以外は通常のマルチプロセス DP(各ランクにサブメッシュを設定)を採用します。このサブメッシュは起動時に検出され、TT_VISIBLE_DEVICES を経由して割り当てられます。
どの構成が採用されたかは、起動ログに表示されます。
デバイス上でのサンプリングと、誰も設定しないフォールバック機能
sample_on_device_mode を設定すると、メッシュプログラムはトークン選択までサンプリング処理を実行し、ロジットではなくトークンを返します。
ログプロバビリティ(logprobs)やペナルティ、許可トークンマスク、悪意ある単語のフィルタリング、カスタムロジットプロセッサなど、多くのリクエストではそのパスを利用できません。本プラグインはこれらのリクエストを拒否するわけでもなく、ユーザーにモードを選択させることもありません。バッチ単位で判断し、デバイス側パスでは表現できない要件が必要な場合は vLLM 独自の LogitProcessor とサンプラーパスへフォールバックし、条件が整えば再びデバイス側パスに戻ります。ホスト側でのサンプリングが必要なリクエストは、結果の正確性を保つために読み戻しのコストがかかりますが、それ以外のケースでは高速パスを維持します。デバッグや A/B 比較を行う場合は always_compat_sampling を指定してホスト側パスを強制できます。
デコードのオーバーラップは非同期読み出しであり、非同期実行モデルではない
このプラグインは、モデルごとの supports_async_decode 宣言に基づいてデコードとホストの処理を並行実行する機能をサポートしています。もし特定のモデルがこの機能の宣言を行っていない場合、プラットフォーム側が非同期スケジューリングを自動的に無効化し、ユーザーが未検証の設定を強制的に有効化するのを防ぎます。
ここでいう「非同期(async)」は、通常の意味よりも狭い範囲を指しており、実態としてはホスト側での読み取り処理の非同期化であり、デバイス側で実行されるスレッドとは異なります。
デコード処理は、read_from_device=False を指定して非同期で実行します。
その後、read_decode_output(..., async_read=True) でホスト側へのデータ転送を開始し、返却されたイベントを提出記録に保存します(これも非同期です)。
最終化の段階になって初めて、ttnn.event_synchronize(...) を用いてこれらのイベントが完了するのを待ちます。
その後に初めて、デバイス上の出力をホスト側のテンソルおよびサンプリング結果に変換します。
図 4: オーバーラップが生まれる場所。これがなければ、デバイスはホストが前ステップの読戻しとサンプリングを行う間待機することになります。一方、非同期デコードでは読戻しが飛行中(in-flight)のままにされるため、ホストは次のステップをスケジューリングしつつ前のステップを終了させることができます。この際、デバイスがいまだ処理中であっても、ブロックする待機が発生するのは最終化時の ttnn.event_synchronize() のみです。
エンジンでは深さ 2 の飛行中キューを保持しており、ブロッキングする前にこれを埋めます。これにより、ホストはステップ N の読戻しが飛行中の間にステップ N+1 をスケジューリングできます。ただし、このオーバーラップが維持されるのはバッチが「安定」している場合に限られます。具体的には、形状が一定で、オンデバイスサンプリングが行われ、構造化出力の管理がなく、プレフィルのリスタートもない状態です。これらの条件のいずれかが崩れると、処理を続ける前に保留中の作業はすべて排水(drain)されます。
つまり、実用上はプレフィルは同期処理のままですが、デコードのオーバーラップは「安定した生成状態」における高速パスであり、すべてのケースに適用される非同期パイプラインではありません。この仕組みが、エグゼキュータの出力スレッドとエンジンスレッドが同じ結果を競走する際にも正しく動作するように保つための最終化管理を含む完全な解説は、プラグインリポジトリの `docs/SCHEDULING.md` に記載されています。
現在の制限事項
TTPlatform では、設定時にサポートされていない組み合わせを拒否または調整するため、実行中に失敗するのではなく、デバイスに到達する前に明確なエラーメッセージが表示されます。
- テンソル並列とパイプライン並列はサポートされていますが、実装方法は異なります。並列化は vLLM の TP/PP ランクではなく、メッシュ形状(
MESH_DEVICE)とモデルの実装によって実現されます。
- 推測デコーディングはまだサポートされていません。
- LoRA もまだサポートされていません。
- プロンプトのログ確率値もまだサポートされておらず、リクエスト検証段階で拒否されます。
- プレフィックスキャッシングは、対応するモデルに対してのみ有効になります。
- 非同期デコーディングのオーバーラップも、その機能を宣言したモデルに対してのみ有効になります。
- 標準的なマルチプロセス DP(データ並列)では MoE モデルには対応していません。内部データ並列を必要とする単一実行型モデル(例:GPT-OSS など)は、レーン DP に統合されます。
- マルチホストサービングはまだサポートされていません。Tenstorrent ハードウェアは単一のマシンを超えてスケーリング可能ですが、現在の TT マルチホストモデルの実装は vLLM のマルチホストパラダイムに直接マッピングされるものではありません。
これらは、ハードウェアやソフトウェアスタック、vLLM プラグイン API に根本的な制限があるわけではなく、現在の Tenstorrent ランタイムとモデル実装における特性です。将来的にはそれぞれがサポートされる予定であり、主要な項目は以下のロードマップに記載されています。
実際に試してみる
まず TT-Metal をインストールし、その環境を有効化してから、リポジトリのルートディレクトリからプラグインをクローンしてインストールスクリプトを実行してください。
git clone https://github.com/tenstorrent/vllm-tt-plugin.git
cd vllm-tt-plugin
source docs/install-vllm-tt.shこのスクリプトは VLLM_TARGET_DEVICE=empty で vLLM をビルドし、tt プラットフォームはランタイム時にプラグインによって提供されます。その後、vLLM を起動してクエリを実行します。
MESH_DEVICE=T3K VLLM_RPC_TIMEOUT=100000 python examples/server_example_tt.pycurl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "meta-llama/Llama-3.1-70B-Instruct", "prompt": "San Francisco is a", "max_tokens": 32}'既存の OpenAI クライアントコードに変更は不要です。
注意: 現在のセットアップでは、tt-metal 環境内でソースから vLLM をビルドしており、バージョンは 0.26.0 です。モデルごとのコマンド、メッシュ形状、必要な環境変数は、プラグインの README および対応する tt-metal のモデルデモに記載されています。
次のステップ
- 非同期デコードのカバレッジ拡大 -
supports_async_decodeを宣言するモデルファミリーを増やし、特にオンデバイスサンプリングモードにおいてドレインを強制する条件を減らします。 - より多くのモデルでのプレフィックスキャッシュ - リクエスト固有の RoPE に対応するレーン DP(データ並列)をサポートし、ビジョンモデルでも利用可能にします。
- 推測デコーディング - メッシュ側のドラフト/検証の仕組みが整った段階で実装されます。
- マルチホストサービング - 1 つのマシンでは収容できない大規模モデルへのスケーリングを実現します。
謝辞
本稿は、Ascend チームが提供した vLLM プラットフォームプラグイン機構と、Spyre チームが設計したプラグ可能なスケジューリングの仕組みを基盤としています。後者の設計がなければ、フェーズベースのスケジューラーを採用する際にも独自フォークが必要となるところでした。また、メッシュアーキテクチャがこの拡張ポイントに適合するよう、vLLM のメンテナーが V1 拡張ポイントを十分に汎用的に保ってくれたことにも感謝します。
本プロジェクトに貢献いただいた多くの有能な方々に心より感謝いたします:Viktor Puš, Tomasz Cheda, Sanjar Adylov, Salar Hosseini。
特に、2 点についてご意見を伺いたいです。1 つ目は、単一実行モデル向けに --data_parallel_size をプロセス内レーンに統合することが適切なユーザーインターフェースであるかどうかです。2 つ目は、次に優先すべきモデルファミリーはどれかという点です。ご意見やプルリクエストは vllm-tt-plugin まで歓迎いたします。また、vLLM の Slack でもお気軽にご連絡ください。
関連記事
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み