mcpField
M
modal-serverless-gpu

modal-serverless-gpu

github.com/davila7クラウド・DevOps33.0k1.1k 回インストール今日更新
リポジトリ

modal-serverless-gpu について

ModalのサーバーレスGPUクラウドで機械学習ワークロードを実行するためのガイドです。Pythonによる環境定義、自動スケーリング、永続ストレージ、APIデプロイを扱います。

主な機能

  1. 01複数GPUのオンデマンド利用
  2. 02Pythonでのクラウド環境定義
  3. 03ゼロから複数GPUへの自動スケーリング
  4. 04Web APIエンドポイントのデプロイ
  5. 05永続ストレージとシークレット管理
  6. 06並列処理とスケジュール実行

活用シーン

  1. 01GPUでの学習や推論の実行
  2. 02機械学習モデルのAPI化
  3. 03バッチデータ処理
  4. 04定期的なMLジョブの実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/davila7/claude-code-templates --skill modal-serverless-gpu

インストール後、Claude Code で/modal-serverless-gpuを入力して読み込まれたか確認します。

同梱ファイルreferences/advanced-usage.mdreferences/troubleshooting.md

詳細

Modal サーバーレス GPU

Modal のサーバーレス GPU クラウドプラットフォームで ML ワークロードを実行するための包括的なガイドです。

Modal を使うタイミング

Modal を使うとよい場合:

  • インフラを管理せずに GPU を多用する ML ワークロードを実行したいとき
  • ML モデルを自動スケーリングする API としてデプロイしたいとき
  • バッチ処理ジョブ(トレーニング、推論、データ処理)を実行したいとき
  • アイドル時のコストをかけず、秒単位の従量課金で GPU を利用したいとき
  • ML アプリケーションのプロトタイピングを素早く行いたいとき
  • スケジュールジョブ(cron のようなワークロード)を実行したいとき

主な機能:

  • サーバーレス GPU: T4、L4、A10G、L40S、A100、H100、H200、B200 をオンデマンドで利用可能
  • Python ネイティブ: インフラを YAML ではなく Python コードで定義
  • 自動スケーリング: ゼロまでスケールダウンし、100 基以上の GPU へ即座にスケールアップ
  • 1 秒未満のコールドスタート: Rust ベースのインフラにより、コンテナを高速に起動
  • コンテナキャッシュ: イメージレイヤーをキャッシュし、迅速な反復開発を実現
  • Web エンドポイント: 関数を、ダウンタイムなしで更新できる REST API としてデプロイ

代わりに検討できるサービス:

  • RunPod: 永続的な状態を持つ、長時間稼働するポッド向け
  • Lambda Labs: 予約制の GPU インスタンス向け
  • SkyPilot: マルチクラウドのオーケストレーションとコスト最適化向け
  • Kubernetes: 複雑なマルチサービスアーキテクチャ向け

クイックスタート

インストール
pip install modal
modal setup  # Opens browser for authentication
GPU を使った Hello World
import modal

app = modal.App("hello-gpu")

@app.function(gpu="T4")
def gpu_info():
    import subprocess
    return subprocess.run(["nvidia-smi"], capture_output=True, text=True).stdout

@app.local_entrypoint()
def main():
    print(gpu_info.remote())

実行: modal run hello_gpu.py

基本的な推論エンドポイント
import modal

app = modal.App("text-generation")
image = modal.Image.debian_slim().pip_install("transformers", "torch", "accelerate")

@app.cls(gpu="A10G", image=image)
class TextGenerator:
    @modal.enter()
    def load_model(self):
        from transformers import pipeline
        self.pipe = pipeline("text-generation", model="gpt2", device=0)

    @modal.method()
    def generate(self, prompt: str) -> str:
        return self.pipe(prompt, max_length=100)[0]["generated_text"]

@app.local_entrypoint()
def main():
    print(TextGenerator().generate.remote("Hello, world"))

コアコンセプト

主要コンポーネント
コンポーネント用途
App関数とリソースのコンテナ
Functionコンピュートスペックを持つサーバーレス関数
Clsライフサイクルフックを持つクラスベースの関数
Imageコンテナイメージの定義
Volumeモデルやデータを保存する永続ストレージ
Secret認証情報を安全に保存する仕組み
実行モード
コマンド説明
modal run script.py実行して終了
modal serve script.pyライブリロードを使った開発
modal deploy script.py永続的なクラウドへのデプロイ

GPU の設定

利用可能な GPU
GPUVRAM適した用途
T416GB低コストの推論、小規模モデル
L424GB推論、Ada Lovelace アーキテクチャ
A10G24GBトレーニング/推論、T4 比で 3.3 倍高速
L40S48GB推論に推奨(コストパフォーマンスが最良)
A100-40GB40GB大規模モデルのトレーニング
A100-80GB80GB非常に大規模なモデル
H10080GB最速、FP8 + Transformer Engine
H200141GBH100 から自動アップグレード、4.8TB/s の帯域幅
B200最新Blackwell アーキテクチャ
GPU 指定のパターン
# Single GPU
@app.function(gpu="A100")

# Specific memory variant
@app.function(gpu="A100-80GB")

# Multiple GPUs (up to 8)
@app.function(gpu="H100:4")

# GPU with fallbacks
@app.function(gpu=["H100", "A100", "L40S"])

# Any available GPU
@app.function(gpu="any")

コンテナイメージ

# Basic image with pip
image = modal.Image.debian_slim(python_version="3.11").pip_install(
    "torch==2.1.0", "transformers==4.36.0", "accelerate"
)

# From CUDA base
image = modal.Image.from_registry(
    "nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04",
    add_python="3.11"
).pip_install("torch", "transformers")

# With system packages
image = modal.Image.debian_slim().apt_install("git", "ffmpeg").pip_install("whisper")

永続ストレージ

volume = modal.Volume.from_name("model-cache", create_if_missing=True)

@app.function(gpu="A10G", volumes={"/models": volume})
def load_model():
    import os
    model_path = "/models/llama-7b"
    if not os.path.exists(model_path):
        model = download_model()
        model.save_pretrained(model_path)
        volume.commit()  # Persist changes
    return load_from_path(model_path)

Web エンドポイント

FastAPI エンドポイントのデコレーター
@app.function()
@modal.fastapi_endpoint(method="POST")
def predict(text: str) -> dict:
    return {"result": model.predict(text)}
フル ASGI アプリ
from fastapi import FastAPI
web_app = FastAPI()

@web_app.post("/predict")
async def predict(text: str):
    return {"result": await model.predict.remote.aio(text)}

@app.function()
@modal.asgi_app()
def fastapi_app():
    return web_app
Web エンドポイントの種類
デコレーターユースケース
@modal.fastapi_endpoint()単純な関数を API 化
@modal.asgi_app()フルな FastAPI/Starlette アプリ
@modal.wsgi_app()Django/Flask アプリ
@modal.web_server(port)任意の HTTP サーバー

動的バッチ処理

@app.function()
@modal.batched(max_batch_size=32, wait_ms=100)
async def batch_predict(inputs: list[str]) -> list[dict]:
    # Inputs automatically batched
    return model.batch_predict(inputs)

シークレット管理

# Create secret
modal secret create huggingface HF_TOKEN=hf_xxx
@app.function(secrets=[modal.Secret.from_name("huggingface")])
def download_model():
    import os
    token = os.environ["HF_TOKEN"]

スケジューリング

@app.function(schedule=modal.Cron("0 0 * * *"))  # Daily midnight
def daily_job():
    pass

@app.function(schedule=modal.Period(hours=1))
def hourly_job():
    pass

パフォーマンス最適化

コールドスタートの軽減
@app.function(
    container_idle_timeout=300,  # Keep warm 5 min
    allow_concurrent_inputs=10,  # Handle concurrent requests
)
def inference():
    pass
モデル読み込みのベストプラクティス
@app.cls(gpu="A100")
class Model:
    @modal.enter()  # Run once at container start
    def load(self):
        self.model = load_model()  # Load during warm-up

    @modal.method()
    def predict(self, x):
        return self.model(x)

並列処理

@app.function()
def process_item(item):
    return expensive_computation(item)

@app.function()
def run_parallel():
    items = list(range(1000))
    # Fan out to parallel containers
    results = list(process_item.map(items))
    return results

共通の設定

@app.function(
    gpu="A100",
    memory=32768,              # 32GB RAM
    cpu=4,                     # 4 CPU cores
    timeout=3600,              # 1 hour max
    container_idle_timeout=120,# Keep warm 2 min
    retries=3,                 # Retry on failure
    concurrency_limit=10,      # Max concurrent containers
)
def my_function():
    pass

デバッグ

# Test locally
if __name__ == "__main__":
    result = my_function.local()

# View logs
# modal app logs my-app

よくある問題

問題解決策
コールドスタートの遅延container_idle_timeout を増やし、@modal.enter() を使用
GPU の OOMより大きな GPU(A100-80GB)を使用し、勾配チェックポイントを有効化
イメージのビルド失敗依存関係のバージョンを固定し、CUDA の互換性を確認
タイムアウトエラーtimeout を増やし、チェックポイントを追加

参考資料

Resources

コメント