Loading...
Loading...
Compare original and translation side by side
pip install modal
modal setup # Opens browser for authenticationpip install modal
modal setup # 打开浏览器进行身份验证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.pyimport 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.pyimport 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"))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"))| Component | Purpose |
|---|---|
| Container for functions and resources |
| Serverless function with compute specs |
| Class-based functions with lifecycle hooks |
| Container image definition |
| Persistent storage for models/data |
| Secure credential storage |
| 组件 | 用途 |
|---|---|
| 函数和资源的容器 |
| 带有计算规格的无服务器函数 |
| 带有生命周期钩子的类式函数 |
| 容器镜像定义 |
| 用于模型/数据的持久化存储 |
| 安全凭证存储 |
| Command | Description |
|---|---|
| Execute and exit |
| Development with live reload |
| Persistent cloud deployment |
| 命令 | 描述 |
|---|---|
| 执行后退出 |
| 开发模式,支持热重载 |
| 持久化云端部署 |
| GPU | VRAM | Best For |
|---|---|---|
| 16GB | Budget inference, small models |
| 24GB | Inference, Ada Lovelace arch |
| 24GB | Training/inference, 3.3x faster than T4 |
| 48GB | Recommended for inference (best cost/perf) |
| 40GB | Large model training |
| 80GB | Very large models |
| 80GB | Fastest, FP8 + Transformer Engine |
| 141GB | Auto-upgrade from H100, 4.8TB/s bandwidth |
| Latest | Blackwell architecture |
| GPU | 显存 | 适用场景 |
|---|---|---|
| 16GB | 低成本推理、小型模型 |
| 24GB | 推理任务、Ada Lovelace架构 |
| 24GB | 训练/推理任务,性能是T4的3.3倍 |
| 48GB | 推荐用于推理任务(最佳性价比) |
| 40GB | 大型模型训练 |
| 80GB | 超大型模型 |
| 80GB | 性能最强,支持FP8与Transformer Engine |
| 141GB | H100自动升级款,带宽4.8TB/s |
| 最新款 | Blackwell架构 |
undefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedvolume = 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)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() # 持久化变更
return load_from_path(model_path)@app.function()
@modal.fastapi_endpoint(method="POST")
def predict(text: str) -> dict:
return {"result": model.predict(text)}@app.function()
@modal.fastapi_endpoint(method="POST")
def predict(text: str) -> dict:
return {"result": model.predict(text)}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_appfrom 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| Decorator | Use Case |
|---|---|
| Simple function → API |
| Full FastAPI/Starlette apps |
| Django/Flask apps |
| Arbitrary HTTP servers |
| 装饰器 | 适用场景 |
|---|---|
| 简单函数转API |
| 完整FastAPI/Starlette应用 |
| Django/Flask应用 |
| 任意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)@app.function()
@modal.batched(max_batch_size=32, wait_ms=100)
async def batch_predict(inputs: list[str]) -> list[dict]:
# 输入会被自动批处理
return model.batch_predict(inputs)undefinedundefined
```python
@app.function(secrets=[modal.Secret.from_name("huggingface")])
def download_model():
import os
token = os.environ["HF_TOKEN"]
```python
@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(schedule=modal.Cron("0 0 * * *")) # 每日午夜
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.function(
container_idle_timeout=300, # 保持预热5分钟
allow_concurrent_inputs=10, # 处理并发请求
)
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.cls(gpu="A100")
class Model:
@modal.enter() # 容器启动时运行一次
def load(self):
self.model = load_model() # 预热阶段加载模型
@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()
def process_item(item):
return expensive_computation(item)
@app.function()
def run_parallel():
items = list(range(1000))
# 分发到并行容器处理
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@app.function(
gpu="A100",
memory=32768, # 32GB内存
cpu=4, # 4核CPU
timeout=3600, # 最长1小时
container_idle_timeout=120,# 保持预热2分钟
retries=3, # 失败重试3次
concurrency_limit=10, # 最大并发容器数
)
def my_function():
passundefinedundefinedundefinedundefined| Issue | Solution |
|---|---|
| Cold start latency | Increase |
| GPU OOM | Use larger GPU ( |
| Image build fails | Pin dependency versions, check CUDA compatibility |
| Timeout errors | Increase |
| 问题 | 解决方案 |
|---|---|
| 冷启动延迟 | 增大 |
| GPU内存不足 | 使用更大显存的GPU(如 |
| 镜像构建失败 | 固定依赖版本,检查CUDA兼容性 |
| 超时错误 | 增大 |