perf: reuse Triton's autotune result across Cherimoya calls (2.7x on every prediction after the first) - #165
Open
jmschrei wants to merge 1 commit into
Open
Conversation
Cherimoya's inference kernels are wrapped in triton.autotune, which
benchmarks its candidates on the first launch for a given shape. That is
right for training, but Chorus spawns a fresh subprocess per call, so the
benchmark is re-run every time to serve a single forward pass -- ~7.6s of
tuning against ~0.96ms of steady-state compute.
Enable Triton's on-disk autotune cache (knobs.autotuning.cache) so a later
process reuses the config autotune already selected. This is a cache, not a
guess: the key is the same shape/dtype tuple autotune keys on, and an unseen
shape falls back to benchmarking. Predictions are bit-identical.
Measured on 1x H200, CATv1 DNASE:K562, medians of 3 at this commit's base:
before after speedup
_predict 11.53s 4.27s 2.70x
predict_variant_effect 22.95s 8.41s 2.73x
The first call on a machine still pays the full ~11.5s to populate the
cache; only later processes benefit. Prediction checksum identical before
and after (341.3908). tests/test_cherimoya.py 50 passed; integration 9
passed, 1 skipped.
The knob has no backing environment variable, so it must be set from Python
before the decorators are evaluated at `import cherimoya`. Tests assert that
ordering on all three load paths, since getting it wrong is silent.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cherimoya's inference kernels are wrapped in
triton.autotune, which benchmarks its candidate configs the first time a kernel is launched for a given shape. That's the right call for training, where a process compiles once and then runs for hours. It's badly mismatched to Chorus, whererun_code_in_environmentspawns a fresh subprocess per call — so the benchmark is re-run every single time, to serve one forward pass.On CATv1's native 2114 bp geometry the first forward costs ~7.6 s against ~0.96 ms steady-state. A one-shot prediction was spending ~99.99% of its GPU time deciding how to run the kernel rather than running it.
Triton 3.6+ can persist the selected config to disk, keyed on the same tuple
autotunekeys on. It's off by default, so this turns it on.This is a cache, not a guess. The config used is the one
autotuneitself benchmarked and picked for that exact key; a shape Chorus hasn't seen falls back to benchmarking. Predictions are bit-identical.Measurements
1× H200, CATv1
DNASE:K562, through Chorus's own API withuse_environment=True, medians of 3. Baseline measured on this same base by reverting only these files:_predictpredict_variant_effectRaw: before
_predict11.42 / 11.55 / 11.53, variant 22.95 / 22.90 / 22.95. After_predict4.32 / 4.21 / 4.27, variant 8.41 / 8.41 / 8.40.Prediction checksum is identical before and after:
341.3908. I confirmed the baseline writes zero autotune cache files, so the two arms are genuinely independent.What this does not do
The first call on a machine is not faster — it still pays the full ~11.5 s and populates the cache. Only later processes benefit. Since Chorus's normal mode is many short-lived subprocess calls, that's the right trade, but a single-call benchmark would show no improvement at all.
The cache is keyed on shape, so a new batch size pays one benchmark before being cached (the background builder at batch 64/256 has its own entry). A cleared
~/.triton, or a Triton / GPU / cherimoya version bump, resets it — all three are part of Triton's cache key.Cherimoya itself is unmodified.
Implementation notes
The knob has no backing environment variable (
knobs.autotuning.cachehasenv=None), so it can't go inEnvironmentRunner._prepare_env—Autotuner.__init__reads it when the decorators are evaluated, which happens atimport cherimoya. It therefore has to be set from Python before that import, on each of the three load paths.chorus/oracles/cherimoya_source/_triton_autotune.py— new; canonical helper and the full rationalechorus/oracles/cherimoya.py—_load_direct, which also coversscripts/build_backgrounds_cherimoya.pyand the in-process testschorusinside the cherimoya env costs ~0.6 s and would eat much of the saving; each carries a pointer to the helper's explanationtry/except (ImportError, AttributeError)so CPU-only and macOS installs (no Triton) are unaffected — aFalsereturn is a missed optimization, never a functional differenceTests
tests/test_cherimoya.py: 50 passed (46 existing + 4 new). Integration: 9 passed, 1 skipped — unchanged.Three of the new tests assert the knob precedes the
cherimoyaimport on each load path. That ordering is load-bearing and fails silently — set it after the import and every call quietly goes back to re-benchmarking, with no error to notice.🤖 Generated with Claude Code