Rustで大規模モデル推論エンジンを構築:candleによる軽量デプロイ実践

技术架构本番環境の AI Agent

なぜRustでLLM推論?

PythonはAI訓練の王者だが、推論デプロイには致命的弱点:GIL、高メモリオーバーヘッド、ゼロコピー不可。

次元 Python (PyTorch) Rust (candle)
ランタイムオーバーヘッド インタプリタ+フレームワークで余分なメモリ ランタイムなし。メモリはほぼモデル重みのみ
コールドスタート 通常10-30秒 約2-5秒(検証環境での実測例、参考値)
メモリ安全性 手動管理 コンパイル時保証

candleフレームワーク

HuggingFaceのRust MLフレームワーク:

  • 純粋Rust実装、Python依存なし
  • CUDA/Metal GPUアクセラレーション
  • ゼロコピーテンソル操作
  • GGML/GGUF量子化対応

推論エンジンコア

pub struct InferenceEngine {
    model: Arc<RwLock<Model>>,
    tokenizer: Tokenizer,
    device: Device,
}

impl InferenceEngine {
    pub async fn generate(&self, prompt: &str, max_tokens: usize) -> anyhow::Result<String> {
        let tokens = self.tokenizer.encode(prompt, true)?;
        let mut input_tokens = tokens.get_ids().to_vec();
        let mut generated_tokens = Vec::new();

        let model = self.model.read().await;

        for _ in 0..max_tokens {
            let input = Tensor::new(&input_tokens, &self.device)?.unsqueeze(0)?;
            let logits = model.forward(&input, input_tokens.len() - 1)?;
            let next_token = self.sample_token(&logits, &generated_tokens)?;
            generated_tokens.push(next_token);
            input_tokens.push(next_token);
        }

        let output = self.tokenizer.decode(&generated_tokens, true)?;
        Ok(output)
    }
}

正直な性能位置づけ

結論から:本記事のエンジンは教育・軽量ユースケース向けであり、candleのスループット上限を示すものではなく、vLLMに勝つこともありません。

上記コードはグローバルRwLockでforwardを直列化し、バッチ処理なしでトークンごとに実行します——物理的に数千tok/sには到達できません。ネットに流布する「candle 8,200 tok/s が vLLM 2,500 を圧倒」のような数字に信頼できる出典はなく、本記事の旧版でも引用していましたが削除しました。

業界の共通認識と独立系ベンチマークの結論は逆です:

  • 高同時実行スループット:PagedAttention+連続バッチ処理を備えるvLLMが明確に上位。candle系のシングルリクエスト実装のスループットは一般にvLLMの約70%程度(モデル・ハードウェア・量子化形式で変動、参考値)。
  • candleの真の強みはデプロイ形態:シングルバイナリ、Python非依存、高速なコールドスタート、低いランタイムメモリオーバーヘッド。

定性比較(デプロイ観点)

次元 vLLM 本記事のcandleエンジン
高同時実行スループット 強い(PagedAttention+連続バッチ) 弱い(バッチなし、リクエスト直列)
単一リクエストのレイテンシ 低い 低い
デプロイ依存 Python+CUDAエコシステム シングルバイナリ、Python不要
コールドスタート 通常10-30秒 約2-5秒(検証環境での実測例、参考値)
ランタイムメモリ Pythonランタイム+フレームワーク ほぼモデル重み+KVキャッシュのみ
適用シーン 本番の高同時実行サービス 教育、エッジ/組み込み、軽量サービス

メモリ使用量の正直な数字

Qwen2.5-7B-Instruct Q4_0の例:

  • 重み:Q4_0量子化後 約4GB(1パラメータあたり約0.55バイト、7B × 0.55 ≈ 3.9GB)
  • KVキャッシュ:コンテキスト長と同時実行数に応じて増加、通常さらに1-2GB
  • 合計:約5-6GB

「7B Q4_0モデルのメモリが1.1GBだけ」という主張は基本算術に反します——重みだけで約4GBです。旧版の当該数字は誤りであり、修正済みです。


まとめ

  1. 軽量デプロイ:単一バイナリ約15MB(ビルド例)、Python非依存、コールドスタート約2-5秒(検証環境の実測例)
  2. メモリ安全性:データ競合なし、ヌルポインタなし、バッファオーバーフローなし
  3. 低ランタイムオーバーヘッド:メモリはほぼモデル重み+KVキャッシュのみ
  4. GILなし:真のマルチスレッド同時実行

正直に言えば、スループットは本構成の売りではありません。高同時実行の本番サービスにはvLLMなどPagedAttention+連続バッチ処理を備えたエンジンを選びましょう。candle構成は教育、エッジデプロイ、デプロイ形態が重要な軽量サービスに適しています。

Rustはスループットで誰かを圧倒するためではなく、推論デプロイにもう一つの形態を与えるもの——訓練はPython、高同時実行はvLLM、軽量/エッジはRust+candle。

#Rust#LLM推理#轻量部署#candle#推理引擎#内存安全