皆さん、こんにちは。数週間この問題に頭を悩ませており、アーキテクチャやMLOpsに関するアドバイスをぜひお願いします。
ローカルのコーディングエージェントのための統一Knowledge Graph / RAGサービスを構築しています。FastAPI経由で単一のDockerコンテナで動作します。初めはWindows(WSL)で問題なく動作していましたが、ネイティブLinuxへ移行したことでストレステスト中に深刻なメモリ制限問題が露呈しました。
ハードウェアの制約:
• 8GBのVRAM(ノートPCのGPU)
• 約16GBのシステムRAM(モデルを読み込むとDockerの制限にすぐ達し、通常は約6GBしか空きがありません)
スタック(モデル):
Embedding: nomic-ai/nomic-embed-text-v2-moe
Reranking: BAAI/bge-reranker-base
Classification: MoritzLaurer/ModernBERT-large-zeroshot-v2.0(テキストペアを4つの関係に分類するために使用: 依存、拡張、矛盾、関連なし)。
問題点 / 悪夢:
これらのモデルにコードの断片と自然文を入力しているため、テキストを過度に切り捨てることはできません。可変長の長いシーケンスを処理できることが必要です。
私が直面したこと:
• レイテンシ vs. OOM: GPUをきれいに保つために torch.cuda.empty_cache() を使用すると、ドライバ同期の影響でリクエストあたりのレイテンシが18〜20秒に急上昇します。これを削除すると、同時リクエスト時にGPUが即座にOOMします。
• システムRAMの爆発(Linux Exit 137): Hugging Face のパイプライン("zero-shot-classification")を使用すると、CPU RAM が著しく膨張します。切り捨てを行わないと、パイプラインはGPUへ送る前にメモリ上で巨大な組み合わせ行列を生成します。Linuxカーネルは瞬時にコンテナを終了します。
• VRAMの急騰: cudnn.benchmark = True は、すべての固有のシーケンス長に対してワークスペースをキャッシュしてしまい、ストレステスト中に自由VRAMの3GBを数秒で使い果たします。
現在の“応急処置”実装:
現時点では、純粋なPython/FastAPIの設定を取っています。HFパイプラインを回避し、ModernBERTの手動NLI推論ループを作成しました。 asyncio.Lock() を使用して逐次実行を強制しています(同時にGPUに触るモデルは1つだけ)し、 del inputs + gc.collect() を用いた決定論的な解放を FastAPI のバックグラウンドタスク経由で行っています。
それは改善されましたが、3分間のストレステストではまだ不安定です。
コミュニティへの質問:
モデルの代替案: 8GBの容量内に収まりつつ、高い精度を維持するZero-Shot NLIとリランキングで、より小型で高速なモデルはありますか?
事前構築アーキテクチャ: 以前は infinity_emb を検討しましたが、カスタムの4択NLI分類ロジックをそのラッパーに統合して、モデルを二重ロードせずに実行するのに苦労しました。Encoderモデル向けに最適化された TEI(Text Generation Inference)、TensorRT、または他のものを検討すべきですか?
提供戦略: 1つのコンシューマGPU上で3つのトランスフォーマーモデルをホストする際、互いのメモリを侵さずに動作させる標準的なデザインパターンはありますか?
モデルの置換、推論エンジンの変更、またはデプロイを再構成してレイテンシを低く保ちつつ、これらのメモリクラッシュを完全に防ぐための提案があれば素晴らしいです。よろしくお願いします!
[リンク] [コメント]