ローカルAIランタイムがモデルの重複コピーを読み込む原因は何ですか?

エヴァ・ウォンテクニカルライター であり ZimaSpaceの常駐ティンカーでもあります。 生涯のオタクであり、 ホームラボとオープンソースソフトウェアに情熱を持っています。彼女は複雑な技術的概念をわかりやすく、 実践的なガイドに翻訳することを専門としています。エヴァはセルフホスティングは楽しくあるべきで、怖がるものではないと信じています。彼女のチュートリアルを通じて、コミュニティが ハードウェアのセットアップを解明する手助けをしています。初めてのNAS構築からDockerコンテナの習得まで。

重複したモデルのコピーは、別々のプロセス、レプリカ、セッション、またはデバイスコンテキストが、読み込まれた重みの割り当てを共有できない場合に発生します。

ホームAIサーバーでは、Web UI、バックグラウンドワーカー、音声サービス、ドキュメントインデクサー、または2つ目のAPIエンドポイントを追加した後、想定していたRAMやVRAMの約2倍が使用されることがあります。ディスク上のモデルファイルは1つのままでも、複数のランタイムオブジェクトが独立した重み、変換済みテンソル、事前パック済みカーネル、キャッシュ、デバイスコンテキストを保持することがあります。重複の中には意図しないものもありますが、同時実行、分離、並列実行のために意図的に作成されるレプリカもあります。

1つのモデルファイルから複数の独立したランタイムオブジェクトが生成されることがある

同じパスから読み込んだからといって、2つのアプリケーションがメモリ上の1つのモデルを参照するとは限りません。各ランタイムインスタンスはチェックポイントを解析し、それぞれ独自のテンソルを割り当てることがあります。

Google Cloudの推論に関するガイダンスでは、プロセスごと、または仮想マシンごとに1つのモデルコピーを読み込む構成を区別しています。

ワーカー数の増加に伴ってメモリがモデルサイズ単位で増える場合、主な原因はインスタンスの複製です。増加幅が小さい場合は、ワーカーごとのキャッシュ、アロケーター、実行コンテキストである可能性が高くなります。

Webサーバーとジョブワーカーは別々のプロセスを起動することが多い

フロントエンドサーバー、キューコンシューマー、スケジューラー、文字起こしサービス、RAGワーカーは、1つのComposeスタックに属していても、それぞれがモデルローダーをインポートすることがあります。

プロセス分離により、各サービスには独自のアドレス空間が与えられます。CPUページはオペレーティングシステムの仕組みで共有できる場合がありますが、通常のフレームワークオブジェクトやGPU割り当てが、自動的に1つの共有モデルサービスになるわけではありません。

重複はプロセスIDとサービス境界に沿って発生します。1つのコンテナを停止するとモデル1個分に近いメモリが解放される場合、そのコンテナは単に中央のランタイムへリクエストを転送していたのではありません。

サービングレプリカは設計上それぞれ独立したコピーである

オートスケーリングシステムは、レプリカを増やすことでスループットを向上させます。レプリカは、他のワーカーが処理中でもリクエストに対応できる独立したワーカーです。

Ray Serveでは、レプリカを別々のアクタープロセスで実行される個別のコピーと定義しています。

トラフィックの急増やオートスケーラーのイベントに連動したメモリ増加は、リークではなく意図的な複製です。追加されたレプリカの縮退に時間がかかる場合でも、原因は選択した同時実行モデルにあります。

複数の推論セッションは初期化子や事前パック済み重みを複製することがある

アプリケーションは、異なるスレッド、エンドポイント、プロファイル、または実行プロバイダーのために、1つのプロセス内で複数のセッションを作成することがあります。

ONNX Runtimeでは、セッションを分けるとメモリオーバーヘッドが増えるため、アロケーター、初期化子、事前パック済み重みをセッション間で共有する方法を説明しています。

1つのプロセスが複数のセッションオブジェクトを所有し、各セッションの初期化時にメモリが増える場合、重複した状態はコンテナ間ではなくアプリケーション内部に存在します。

フォークしてもアクセラレーター上の重みが共有されるとは限らない

親プロセスがワーカー作成前にモデルを読み込むと、コピーオンライトによってCPUページが共有されているように見えることがあります。しかし、アクセラレーターの初期化と変更可能なランタイム状態によって、この前提は複雑になります。

PyTorchのマルチプロセスに関するガイダンスでは、テンソルがプロセス間で共有メモリの仕組みを利用できると説明していますが、共有には明示的で互換性のある設計が必要です。

ワーカーがモデルをGPUへ移動したり、重みを変更したり、キャッシュを構築したり、spawn後に初期化したりすると、元のCPUチェックポイントページが共有されていても、新しいコピーが割り当てられることがあります。

別々のCUDAコンテキストはプロセスごとのデバイス状態を追加する

1つのGPUを使用する2つのプロセスは、特別な共有アーキテクチャを使わない限り、通常は別々のCUDAコンテキストを通じて動作します。

NVIDIAは、複数のCUDAアプリケーションプロセスが一般にメモリオーバーヘッドを伴う複数のコンテキストを作成すると説明しています。

コンテキストのオーバーヘッド自体は、完全なモデルの2つ目のコピーではありません。しかし、重複した重み、カーネル、ワークスペース、キャッシュに伴って発生することがあります。そのため、チェックポイントサイズより小さいメモリ増加でも、プロセスの重複が原因である可能性があります。

1つのGPU上の2つのランタイムインスタンスは、それぞれ独立してメモリを確保する

ダッシュボードが1つのモデルサーバーを起動する一方で、自動化サービスが同じチェックポイントとデバイスを指定して別のサーバーを起動することがあります。

vLLMのドキュメントでは、GPUメモリ使用率はインスタンスごとの制限であると説明し、1つのGPUの容量を2つのインスタンスで分割する例を示しています。

各エンドポイントが独自のリスナー、ログ、スケジューラー、KVキャッシュを持つ場合、2つのプロセスは独立した推論エンジンです。共有モデルディレクトリによって重複ダウンロードは防げますが、ランタイム割り当ての重複は防げません。

リロードによって新しいプロセスと並行して古いプロセスが残ることがある

ホットリローダー、スーパーバイザー、ローリングアップデート、シャットダウンの失敗、ヘルスチェックによる再起動によって、古いワーカーがモデルを解放する前に置き換え用のプロセスが起動することがあります。

この原因は、開始時刻が異なるほぼ同一のプロセスが一時的または継続的に2つ存在する状態として現れます。リクエストは新しいプロセスにしか届かない一方で、古いプロセスがRAMやVRAMを保持し続けることがあります。

ZimaSpaceの記事「ホームサーバーでAIランタイム状態をモデルファイルから分離する理由」では、その境界を説明しています。1つのチェックポイントキャッシュは複数のデプロイメントで利用できますが、読み込まれるコピーの数はサービス構成によって決まります。

FAQ

ディスク上のモデルファイルが1つなら、RAM上のコピーも1つだけですか?

いいえ。複数のプロセスやセッションが同じファイルを個別に読み込み、それぞれ独自のテンソル、キャッシュ、実行状態を割り当てることがあります。

追加されたコピーはすべてメモリリークですか?

いいえ。レプリカ、テンソル並列ワーカー、フォールバックランタイム、分離されたサービスは、意図的に追加の状態を割り当てることがあります。リークは、対応する稼働中のランタイムオブジェクトがないまま増え続けます。

コンテナは自動的に1つのGPUモデルを共有できますか?

いいえ。コンテナは同じデバイスとファイルにアクセスできますが、読み込み済みモデルの割り当てを再利用するには、共有サービングプロセスまたは明示的なプロセス間設計が必要です。

テック&AIハブ

もっと読む

Get More Builds Like This

Stay in the Loop

Get updates from Zima - new products, exclusive deals, and real builds from the community.

Stay in the Loop preferences

We respect your inbox. Unsubscribe anytime.