Control CPU, memory, GPU, and disk allocation with the @resources decorator
The @resources decorator specifies compute requirements for workflow steps independently of the execution platform. This makes your flows portable across AWS Batch, Kubernetes, and other compute backends.
@resources(cpu=8, memory=32000, gpu=2)@stepdef train(self): # Same resource spec works on both platforms pass
Run on different platforms:
# Run on AWS Batchpython myflow.py run --with batch# Run on Kubernetespython myflow.py run --with kubernetes# Resources automatically applied to whichever platform you choose
@resources(cpu=1)@stepdef light_task(self): # Single CPU for light computation pass@resources(cpu=8)@stepdef parallel_task(self): # 8 CPUs for parallel processing import multiprocessing with multiprocessing.Pool(8) as pool: results = pool.map(expensive_func, data)
Specify CPU as an integer. Fractional CPUs (like 0.5) are not supported in @resources.
# Light data processing@resources(cpu=2, memory=8000)# Medium ML training@resources(cpu=4, memory=16000)# Large dataset processing@resources(cpu=8, memory=32000)# Deep learning with GPU@resources(cpu=8, memory=32000, gpu=1)# Multi-GPU training@resources(cpu=16, memory=64000, gpu=4)
Always prefer @resources over platform-specific parameters:
# Good: Portable across platforms@batch@resources(cpu=4, memory=16000)@stepdef train(self): pass# Less good: Locked to AWS Batch@batch(cpu=4, memory=16000)@stepdef train(self): pass
Profile before scaling
Don’t guess resource needs. Profile first:
Run locally or with minimal resources
Monitor actual usage (CPU, memory, disk)
Scale up based on measurements
Add 20-30% buffer for safety
Consider cost vs performance
More resources = higher cost. Balance performance and cost:
# Fast but expensive@resources(cpu=32, memory=128000)# Slower but cheaper@resources(cpu=4, memory=16000)
Sometimes 2x resources doesn’t mean 2x speed.
Set GPU memory appropriately
GPUs need sufficient CPU memory for data loading:
# Insufficient CPU memory for GPU training@resources(gpu=1, memory=4096) # Too little!# Better: GPU training needs CPU memory for data@resources(gpu=1, memory=32000) # Much better
Symptoms: Process killed with exit code 137 or OOMKilledSolutions:
Increase memory parameter
Process data in smaller chunks
Use memory-efficient algorithms
Clear intermediate variables
Use generators instead of loading all data
# Before: OOM@resources(memory=8000)@stepdef process(self): data = load_all_data() # 20GB dataset! result = process(data)# After: Fixed@resources(memory=8000)@stepdef process(self): result = [] for chunk in load_data_chunks(): # Process 1GB at a time result.append(process(chunk))
Insufficient CPU performance
Symptoms: Step runs but very slowlySolutions:
Profile to find bottlenecks
Increase cpu if CPU-bound
Parallelize with multiprocessing
Consider algorithm optimization first
# Slow@resources(cpu=1)@stepdef process(self): results = [expensive_func(x) for x in large_list]# Faster@resources(cpu=8)@stepdef process(self): from multiprocessing import Pool with Pool(8) as pool: results = pool.map(expensive_func, large_list)
GPU not detected
Symptoms: CUDA not available despite gpu=1Solutions: