Modalとは?
Modalは、Pythonスクリプトをそのままクラウド上のGPUで実行できるサーバーレスプラットフォームです。「GPUクラウド界のHeroku」と表現されるように、インフラ管理の複雑さを抽象化し、開発者はコードに集中できます。
Modalの最大の特徴
コマンド実行からわずか15秒でGPU実行開始
従来のGPUクラウドサービス(RunPod、Lambda Labsなど)では、インスタンス起動だけで5分程度かかりますが、Modalは圧倒的に高速です。
Modalのメリット・デメリット
メリット
1. 開発速度の圧倒的な向上
- インフラコードが不要: Dockerfileもレジストリも不要
- 一つのファイルで完結: Pythonデコレータだけで環境指定
- ローカルとリモートのシームレス連携: ファイル転送も簡単
実際の開発効率の比較:
- 従来のサービス: 1時間に10回程度の試行錯誤(5分起動 + 30秒実行)
- Modal: 1時間に20〜30回の試行錯誤(15秒起動 + 30秒実行)
2. RunPodとの比較で優れている点
RunPodの場合:
# 1. Dockerイメージをビルド
docker build -t myimage:v1 .
# 2. レジストリにpush
docker push registry.example.com/myimage:v1
# 3. RunPodで設定
# - イメージタグを手動で指定
# - 毎回更新が必要
Modalの場合:
# たったこれだけ
import modal
app = modal.App()
image = modal.Image.debian_slim().pip_install("torch")
@app.function(gpu="A100")
def train():
# ここに処理を書くだけ
pass
3. その他の便利機能
-
ローカルパッケージの転送が簡単:
.mount()で一発 - Pythonオブジェクトをそのまま引数に渡せる: シリアライズ不要
- オートスケール: 使わない時は自動停止(課金ゼロ)
- 毎月$30の無料クレジット: 小規模実験なら実質無料
デメリット
1. 料金が高め
- T4: 約$0.59/時間
- A100: 約$2.5/時間
- RunPod比較で1.5〜2倍程度高い
2. サブスクリプションプランなし
- 完全従量課金のみ
- 長時間のトレーニングには不向き
3. 完全なコンテナ環境ではない
- 関数実行プラットフォーム
- 対話的な開発には向かない場合も
4. 学習コスト
- ローカル/リモート両方で同じスクリプトが実行される仕組み
- Pythonバージョンの違いなどに注意が必要
どんな時にModalを使うべきか?
Modalが最適:
- 頻繁に環境を変える実験
- 短時間の推論タスク
- パラメータ探索などの並列実行
- プロトタイプ開発
RunPodなどが最適:
- 長時間のトレーニング(数時間〜数日)
- コスト重視
- 対話的な開発環境が欲しい
- 完全なコンテナ制御が必要
セットアップ手順
1. インストール
# uvを使う場合
uv init --app
uv add modal
# pipを使う場合
pip install modal
2. アカウント作成とログイン
- Modal公式サイトでアカウント作成
- ターミナルでログイン:
modal setup
基本的な使い方
Hello World
import modal
app = modal.App()
image = modal.Image.debian_slim().pip_install("torch", "numpy")
@app.function(gpu="T4", image=image)
def train_simple_model():
import torch
print(f"使用デバイス: {torch.cuda.get_device_name(0)}")
# 簡単な計算
X = torch.randn(1000, 20).cuda()
y = torch.randn(1000, 1).cuda()
model = torch.nn.Linear(20, 1).cuda()
optimizer = torch.optim.Adam(model.parameters())
for epoch in range(100):
optimizer.zero_grad()
pred = model(X)
loss = torch.nn.functional.mse_loss(pred, y)
loss.backward()
optimizer.step()
if epoch % 20 == 0:
print(f"Epoch {epoch}, Loss: {loss.item():.4f}")
return f"訓練完了!"
@app.local_entrypoint()
def main():
result = train_simple_model.remote()
print(result)
実行
modal run gpu_test.py
実践: NVIDIA Cosmosを動かす
ここからが本題です。既存のDockerイメージ(NVIDIA Cosmosなど)をModalで使う方法を解説します。
方法1: レジストリからイメージを取得
import modal
# NVIDIA Cosmosの公式イメージを使用
image = modal.Image.from_registry(
"nvcr.io/nvidia/cosmos/cosmos-predict2-container:1.1"
)
app = modal.App("cosmos-inference")
@app.function(
image=image,
gpu="A100",
timeout=3600,
secrets=[modal.Secret.from_name("nvidia-ngc")] # NGC認証が必要な場合
)
def run_cosmos_inference(input_video_path: str):
"""Cosmosで推論を実行"""
import subprocess
import os
# Cosmosの推論スクリプトを実行
result = subprocess.run(
[
"python", "/workspace/inference.py",
"--input", input_video_path,
"--output", "/tmp/output.mp4"
],
capture_output=True,
text=True
)
if result.returncode == 0:
# 結果を読み込んで返す
with open("/tmp/output.mp4", "rb") as f:
return f.read()
else:
raise Exception(f"Error: {result.stderr}")
@app.local_entrypoint()
def main(video_path: str):
print("Cosmosでの推論を開始...")
result = run_cosmos_inference.remote(video_path)
# 結果を保存
with open("output.mp4", "wb") as f:
f.write(result)
print("完了!output.mp4に保存しました")
方法2: イメージに追加設定を加える
import modal
# Cosmosイメージにカスタム設定を追加
image = (
modal.Image.from_registry(
"nvcr.io/nvidia/cosmos/cosmos-predict2-container:1.1"
)
.pip_install("opencv-python", "pillow") # 追加パッケージ
.run_commands(
"apt-get update && apt-get install -y ffmpeg" # 追加ツール
)
)
app = modal.App("cosmos-custom")
@app.function(image=image, gpu="A100")
def process_with_cosmos():
import os
# Cosmosコンテナ内でコマンド実行
os.system("cd /workspace && python your_custom_script.py")
return "処理完了"
方法3: ローカルファイルをマウント
import modal
image = modal.Image.from_registry(
"nvcr.io/nvidia/cosmos/cosmos-predict2-container:1.1"
)
app = modal.App("cosmos-with-data")
@app.function(
image=image,
gpu="A100",
mounts=[
modal.Mount.from_local_dir(
"./input_videos",
remote_path="/data/inputs"
)
]
)
def batch_process():
"""複数の動画を一括処理"""
import os
import subprocess
input_dir = "/data/inputs"
output_dir = "/tmp/outputs"
os.makedirs(output_dir, exist_ok=True)
# すべての動画を処理
for video_file in os.listdir(input_dir):
if video_file.endswith('.mp4'):
input_path = os.path.join(input_dir, video_file)
output_path = os.path.join(output_dir, f"out_{video_file}")
subprocess.run([
"python", "/workspace/inference.py",
"--input", input_path,
"--output", output_path
])
return "バッチ処理完了"
NGC認証が必要な場合
NVIDIA NGC Catalogのプライベートイメージを使う場合、認証情報をModal Secretsに保存します。
# Modalのダッシュボードで以下を設定:
# Secret名: nvidia-ngc
# NGC_API_KEY: your_ngc_api_key
@app.function(
image=image,
gpu="A100",
secrets=[modal.Secret.from_name("nvidia-ngc")]
)
def authenticated_run():
# NGC認証が自動的に行われる
pass
実行例
# 基本的な実行
modal run cosmos_inference.py
# コマンドライン引数を渡す
modal run cosmos_inference.py --video-path ./input.mp4
# デプロイして永続化
modal deploy cosmos_inference.py
便利なTips
1. 複数GPU使用
@app.function(gpu="A100:2") # A100を2つ
def multi_gpu_training():
import torch
print(f"{torch.cuda.device_count()}個のGPU使用中")
2. Volumeで結果を永続化
volume = modal.Volume.from_name("cosmos-outputs", create_if_missing=True)
@app.function(
image=image,
gpu="A100",
volumes={"/outputs": volume}
)
def save_results():
# /outputsに保存したファイルは永続化される
import torch
torch.save(model, "/outputs/model.pth")
ローカルにダウンロード:
modal volume get cosmos-outputs model.pth ./local_model.pth
3. クラスベースのリモートオブジェクト
@app.cls(gpu="A100", image=image)
class CosmosProcessor:
def __init__(self):
# モデルのロードなど(1回だけ実行)
self.model = load_cosmos_model()
@modal.method()
def process(self, video_data):
# 何度も呼び出せる
return self.model.inference(video_data)
@app.local_entrypoint()
def main():
processor = CosmosProcessor()
# 複数の動画を処理(モデルロードは1回だけ)
for video in videos:
result = processor.process.remote(video)
トラブルシューティング
インスタンスが勝手に増える問題
Modalはデフォルトでオートスケーリングします。これを制御するには:
@app.cls(
gpu="A100",
concurrency_limit=1, # 同時実行は1つまで
allow_concurrent_inputs=100 # キューには100個まで
)
class Processor:
@modal.method()
def process(self, data):
return result
Pythonバージョンの不一致
ローカルとリモートのPythonバージョンが異なる場合、エラーが発生することがあります。
# イメージでPythonバージョンを明示
image = modal.Image.from_registry(
"nvcr.io/nvidia/cosmos/cosmos-predict2-container:1.1",
add_python="3.10" # Python 3.10を使用
)
料金の目安
- T4: $0.59/時間(約90円/時間)
- A100: $2.5/時間(約375円/時間)
- 毎月$30の無料クレジット付き
実例:
- 2分の実験(環境構築含む): 約$0.02
- 2回目以降(イメージキャッシュ済み): さらに安い
短時間の処理なら数セント程度で最新GPUが利用できます。
まとめ
Modalを選ぶべき場合
- ✅ 頻繁な試行錯誤が必要
- ✅ 短時間の推論・実験
- ✅ インフラ管理の手間を削減したい
- ✅ プロトタイプ開発
RunPodなど他サービスを選ぶべき場合
- ✅ 長時間のトレーニング
- ✅ コスト最優先
- ✅ 完全なコンテナ制御が必要
- ✅ 対話的な開発環境
Modalは「15秒でGPUが動く」という圧倒的な開発速度が魅力です。特にNVIDIA Cosmosのような複雑な環境でも、Dockerイメージを指定するだけで簡単に動かせるのは大きなメリットです。
毎月$30の無料枠があるので、まずは試してみることをおすすめします!