2.0 KiBLFS
2.0 KiBLFS
Getting Started with Modal
Basic Structure
Every Modal script follows this pattern:
import modal
# 1. Create an app
app = modal.App("my-training-app")
# 2. Define the container image
image = modal.Image.debian_slim(python_version="3.11").pip_install(
"torch",
"einops",
"numpy",
)
# 3. Define a GPU function
@app.function(gpu="A100", image=image, timeout=3600)
def train():
import torch
device = torch.device("cuda")
print(f"Using GPU: {torch.cuda.get_device_name(0)}")
# Your training code here
return results
# 4. Local entrypoint
@app.local_entrypoint()
def main():
results = train.remote()
print(results)
Running Scripts
# Set up Modal token (if not already done)
modal token set --token-id <id> --token-secret <secret>
# Run the script
modal run train_modal.py
# Run in background
modal run --detach train_modal.py
Key Concepts
| Concept | Description |
|---|---|
App |
Container for your Modal functions |
Image |
Container image with dependencies |
@app.function |
Decorator to mark functions for remote execution |
@app.local_entrypoint |
Entry point that runs locally |
.remote() |
Call a function remotely on Modal infrastructure |
Image Building
Install dependencies at image build time, not runtime:
# CORRECT - install in image
image = modal.Image.debian_slim(python_version="3.11").pip_install(
"torch",
"einops",
)
# WRONG - install at runtime (slow, unreliable)
@app.function(...)
def train():
import subprocess
subprocess.run(["pip", "install", "torch"]) # Don't do this
Print Statements
Print statements in remote functions appear in Modal logs in real-time:
@app.function(gpu="A100", image=image, timeout=3600)
def train():
print("Starting training...") # Appears in logs
for step in range(100):
if step % 10 == 0:
print(f"Step {step}") # Progress updates
return {"done": True}