Skip to main content
skill CX Codex

modal-serverless-gpu — Claude Code skill: GPU in the cloud

A skill for running ML workloads on Modal's serverless GPUs: training, inference, batch jobs. Useful when you'd rather not manage a cluster yourself.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add Orchestra-Research/AI-Research-SKILLs --skill modal-serverless-gpu -a claude-code
npx skills add Orchestra-Research/AI-Research-SKILLs --skill modal -a claude-code
Open on GitHub

What modal-serverless-gpu does

The skill covers Modal, a cloud platform that hands out GPUs on demand. It walks through the core pieces: App, Function, Cls, Image, Volume, Secret. Everything is configured in Python, no YAML.

There are working examples: an inference endpoint built on transformers, web endpoints via @modal.fastapi_endpoint and @modal.asgi_app, dynamic batching, secrets, cron schedules. Cold starts get their own section — container_idle_timeout and loading the model inside @modal.enter().

You need modal>=0.64.0 and authentication: modal setup opens a browser. For inference the skill points to L40S as the best cost-to-performance pick, and for long-running pods with persistent state it suggests looking at RunPod instead.

What it helps with

  • train a model on a GPU without owning a cluster
  • ship an ML model as an auto-scaling API
  • run batch data processing across several GPUs
  • cache model weights between runs with a Volume
  • set up a cron job for recurring inference

Example prompts for the agent

  • Write a Modal app with an A10G GPU for transformers inference
  • How do I expose a FastAPI app in Modal using asgi_app?
  • Set up dynamic batching for batch_predict in Modal

How to install modal-serverless-gpu

1Skills CLI (Vercel)

npx skills add Orchestra-Research/AI-Research-SKILLs --skill modal-serverless-gpu -a claude-code
npx skills add Orchestra-Research/AI-Research-SKILLs --skill modal -a claude-code

2Manually: put the files in place

~/.claude/skills/modal/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/modal/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about modal-serverless-gpu

How do I install modal-serverless-gpu in Claude?

Run npx skills add Orchestra-Research/AI-Research-SKILLs --skill modal-serverless-gpu -a claude-code. The skill file lands at ~/.claude/skills/modal/SKILL.md.

What does modal-serverless-gpu do?

It documents running ML workloads on Modal's serverless GPUs: GPU configuration, container images, persistent storage, web endpoints and schedules. All through Python code.

What do I need to use the skill?

The modal>=0.64.0 package and authentication via modal setup. For private Hugging Face models you'll need a secret holding the token.

Source text

SKILL.md · MIT
---
name: modal-serverless-gpu
description: Serverless GPU cloud platform for running ML workloads. Use when you need on-demand GPU access without infrastructure management, deploying ML models as APIs, or running batch jobs with automatic scaling.
version: 1.0.0
author: Orchestra Research
license: MIT
tags: [Infrastructure, Serverless, GPU, Cloud, Deployment, Modal]
dependencies: [modal>=0.64.0]
---

# Modal Serverless GPU

Comprehensive guide to running ML workloads on Modal's serverless GPU cloud platform.

## When to use Modal

**Use Modal when:**
- Running GPU-intensive ML workloads without managing infrastructure
- Deploying ML models as auto-scaling APIs
- Running batch processing jobs (training, inference, data processing)
- Need pay-per-second GPU pricing without idle costs
- Prototyping ML applications quickly
- Running scheduled jobs (cron-like workloads)

**Key features:**
- **Serverless GPUs**: T4, L4, A10G, L40S, A100, H100, H200, B200 on-demand
- **Python-native**: Define infrastructure in Python code, no YAML
- **Auto-scaling**: Scale to zero, scale to 100+ GPUs instantly
- **Sub-second cold starts**: Rust-based infrastructure for fast container launches
- **Container caching**: Image layers cached for rapid iteration
- **Web endpoints**: Deploy functions as REST APIs with zero-downtime updates

**Use alternatives instead:**
- **RunPod**: For longer-running pods with persistent state
- **Lambda Labs**: For reserved GPU instances
- **SkyPilot**: For multi-cloud orchestration and cost optimization
- **Kubernetes**: For complex multi-service architectures

## Quick start

### Installation

```bash
pip install modal
modal setup  # Opens browser for authentication
```

### Hello World with GPU

```python
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())
```

Run: `modal run hello_gpu.py`

### Basic inference endpoint

```python
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"))
```

## Core concepts

### Key components

| Component | Purpose |
|-----------|---------|
| `App` | Container for functions and resources |
| `Function` | Serverless function with compute specs |
| `Cls` | Class-based functions with lifecycle hooks |
| `Image` | Container image definition |
| `Volume` | Persistent storage for models/data |
| `Secret` | Secure credential storage |

### Execution modes

| Command | Description |
|---------|-------------|
| `modal run script.py` | Execute and exit |
| `modal serve script.py` | Development with live reload |
| `modal deploy script.py` | Persistent cloud deployment |

## GPU configuration

### Available GPUs

| GPU | VRAM | Best For |
|-----|------|----------|
| `T4` | 16GB | Budget inference, small models |
| `L4` | 24GB | Inference, Ada Lovelace arch |
| `A10G` | 24GB | Training/inference, 3.3x faster than T4 |
| `L40S` | 48GB | Recommended for inference (best cost/perf) |
| `A100-40GB` | 40GB | Large model training |
| `A100-80GB` | 80GB | Very large models |
| `H100` | 80GB | Fastest, FP8 + Transformer Engine |
| `H200` | 141GB | Auto-upgrade from H100, 4.8TB/s bandwidth |
| `B200` | Latest | Blackwell architecture |

### GPU specification patterns

```python
# 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")
```

## Container images

```python
# 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")
```

## Persistent storage

```python
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 endpoints

### FastAPI endpoint decorator

```python
@app.function()
@modal.fastapi_endpoint(method="POST")
def predict(text: str) -> dict:
    return {"result": model.predict(text)}
```

### Full ASGI app

```python
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 endpoint types

| Decorator | Use Case |
|-----------|----------|
| `@modal.fastapi_endpoint()` | Simple function → API |
| `@modal.asgi_app()` | Full FastAPI/Starlette apps |
| `@modal.wsgi_app()` | Django/Flask apps |
| `@modal.web_server(port)` | Arbitrary HTTP servers |

## Dynamic batching

```python
@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)
```

## Secrets management

```bash
# Create secret
modal secret create huggingface HF_TOKEN=hf_xxx
```

```python
@app.function(secrets=[modal.Secret.from_name("huggingface")])
def download_model():
    import os
    token = os.environ["HF_TOKEN"]
```

## Scheduling

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

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

## Performance optimization

### Cold start mitigation

```python
@app.function(
    container_idle_timeout=300,  # Keep warm 5 min
    allow_concurrent_inputs=10,  # Handle concurrent requests
)
def inference():
    pass
```

### Model loading best practices

```python
@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)
```

## Parallel processing

```python
@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
```

## Common configuration

```python
@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
```

## Debugging

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

# View logs
# modal app logs my-app
```

## Common issues

| Issue | Solution |
|-------|----------|
| Cold start latency | Increase `container_idle_timeout`, use `@modal.enter()` |
| GPU OOM | Use larger GPU (`A100-80GB`), enable gradient checkpointing |
| Image build fails | Pin dependency versions, check CUDA compatibility |
| Timeout errors | Increase `timeout`, add checkpointing |

## References

- **[Advanced Usage](references/advanced-usage.md)** - Multi-GPU, distributed training, cost optimization
- **[Troubleshooting](references/troubleshooting.md)** - Common issues and solutions

## Resources

- **Documentation**: https://modal.com/docs
- **Examples**: https://github.com/modal-labs/modal-examples
- **Pricing**: https://modal.com/pricing
- **Discord**: https://discord.gg/modal

© Orchestra Research · MIT · Orchestra-Research/AI-Research-SKILLs

Similar skills

Everything for DevOps and infrastructure →

From the same set66

nanogpt This skill guides work with a small PyTorch GPT implementation. Use it to study transformers, train on Shakespeare, or adapt the model to your own text. CX Codex +1 956installs openrlhf-training A skill that hands your agent ready commands for PPO, GRPO, RLOO and DPO runs on models from 7B to 70B+. Useful when training spans several GPUs or nodes. CX Codex +1 954installs distributed-llm-pretraining-torchtitan Configures distributed LLM pretraining using torchtitan with 4D parallelism (FSDP2, TP, PP, CP). Useful for scaling Llama 3.1 or DeepSeek V3 across 8 to 512+ GPUs. CX Codex +1 954installs transformer-lens-interpretability This skill guides TransformerLens research on transformer internals, from activation caching and attention analysis to activation patching experiments. CX Codex +1 954installs sglang Equips your agent with patterns for serving LLMs via SGLang, configuring RadixAttention prefix caching, and decoding constrained JSON. CX Codex +1 954installs evaluating-code-models Runs code-model benchmarks and reports pass@k metrics. Use it to compare models, test language coverage, or measure generated code quality. CX Codex +1 953installs pyvene-interventions This skill guides causal intervention experiments on PyTorch models using pyvene. It covers causal tracing and activation patching on neural architectures. CX Codex +1 952installs sentencepiece A skill that walks the agent through training and running a SentencePiece tokenizer on raw text, with BPE or Unigram. CX Codex +1 952installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor