modal-gpu-retry
Install
pip install modal-gpu-retry
What it does
Modal's native retries= reruns a failed job on the same hardware, which doesn't help
with OOM errors since the rerun will just run out of memory again. modal-gpu-retry reuses the same retries
argument but takes a list of GPUs and escalates to the next one on each failure.
@app.function(gpu="L40S", retries=["A100", "H100"])
If the job OOMs on the L40S it reruns on the A100, then the H100.
Usage
To integrate with your existing Modal scripts, there are exactly two changes needed to be made. Modify the app initialization to use modal_gpu_retry instead of modal:
app = modal.App("my-evals") # before
app = modal_gpu_retry.App("my-evals") # after
and give the decorator a list-valued retries=[...] containing the fallback GPUs:
@app.function(gpu="L40S", image=image) # before
@app.function(gpu="L40S", retries=["A100", "H100"], image=image) # after
Your code should look like this now:
import modal
import modal_gpu_retry
app = modal_gpu_retry.App("my-evals")
image = modal.Image.debian_slim().pip_install("torch")
@app.function(gpu="L40S", retries=["A100", "H100"], image=image)
def run_eval(config):
... # if this OOMs on L40S, it runs again on A100, then H100
@app.local_entrypoint()
def main():
results = list(run_eval.map(configs))
You can run it as normal with the Modal CLI, for example modal run evals.py works just fine.
The retries= value decides the behavior:
retries=3: native Modal (rerun the same GPU).retries=["A100", "H100"]: escalate to a bigger GPU each time.retries=[]: same asretries=0.
Exhausted jobs come back in place
If a job fails on every GPU, you get a GPURetryExhausted in the results instead of
an exception, so one bad job doesn't kill the batch:
results = list(run_eval.map(configs))
dead = [c for c, r in zip(configs, results, strict=True)
if isinstance(r, modal_gpu_retry.GPURetryExhausted)]
Detached runs
.remote, .map, and .starmap run the retry loop in your process, so it stops if
you disconnect. modal run --detach doesn't help: it keeps the app alive but the loop
still runs locally. For escalation that survives a disconnect, modal deploy your app and
use .spawn_map, which runs the loop in a CPU orchestrator on Modal:
handle = run_eval.spawn_map(configs)
results = handle.get() # later, or from a different process
Reconnect from anywhere with modal_gpu_retry.GPURetryCall.from_id(call_id).
Notes
- A few
modal runCLI patterns behave unexpectedly, such as targeting the wrapped function directly. See the examples README. - Your class/function appears in the Modal dashboard under a
_mgr_real_prefix; that's how the wrapper keeps your call sites unchanged without breaking how Modal loads your class in the container. - It works on
@app.clstoo, and.remote,.map, and.starmapkeep their usual call sites. - You don't need to modify your image because the library will install itself on the image you pass into
modal_gpu_retry.Appviaimage=automatically.
License
MIT. This is a community wrapper around the modal SDK and isn't affiliated with Modal.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file modal_gpu_retry-0.0.4.tar.gz.
File metadata
- Download URL: modal_gpu_retry-0.0.4.tar.gz
- Upload date:
- Size: 259.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
379204101a222c05d68ad61dad1bf8d88867ed88b32665a64243b670cc0bc5a6
|
|
| MD5 |
acfca267de8d4f5c03f697b9b30ce308
|
|
| BLAKE2b-256 |
c6d4765bad608408a414fad2ce45a99539a3ef326368e570f1c34124adcd4e27
|
Provenance
The following attestation bundles were made for modal_gpu_retry-0.0.4.tar.gz:
Publisher:
publish.yml on alexkranias/modal-gpu-retry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
modal_gpu_retry-0.0.4.tar.gz -
Subject digest:
379204101a222c05d68ad61dad1bf8d88867ed88b32665a64243b670cc0bc5a6 - Sigstore transparency entry: 1873720011
- Sigstore integration time:
-
Permalink:
alexkranias/modal-gpu-retry@81678285b3a1c407bfd7a9521b8fb8b77b463658 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/alexkranias
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@81678285b3a1c407bfd7a9521b8fb8b77b463658 -
Trigger Event:
release
-
Statement type:
File details
Details for the file modal_gpu_retry-0.0.4-py3-none-any.whl.
File metadata
- Download URL: modal_gpu_retry-0.0.4-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1c9a2cd301ba899441e6b796ff0a406f73abacaa9b5deb543a8f0d915cb8b00
|
|
| MD5 |
8a215827dd9cec29412c2373c3f23ac0
|
|
| BLAKE2b-256 |
ef6c77e631c1dba88c0a2935d86d7b3d938ceb1989c045ccdf4271443820ccf4
|
Provenance
The following attestation bundles were made for modal_gpu_retry-0.0.4-py3-none-any.whl:
Publisher:
publish.yml on alexkranias/modal-gpu-retry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
modal_gpu_retry-0.0.4-py3-none-any.whl -
Subject digest:
e1c9a2cd301ba899441e6b796ff0a406f73abacaa9b5deb543a8f0d915cb8b00 - Sigstore transparency entry: 1873720038
- Sigstore integration time:
-
Permalink:
alexkranias/modal-gpu-retry@81678285b3a1c407bfd7a9521b8fb8b77b463658 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/alexkranias
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@81678285b3a1c407bfd7a9521b8fb8b77b463658 -
Trigger Event:
release
-
Statement type: