Repository navigation
fix(launch): default TRITON_CACHE_DIR to a node-local path - #3877
Merged
Merged
Conversation
faresobeid
force-pushed
the
fix/triton-cache-node-local
branch
from
October 6, 2026 17:19
70e3001 to
ff9d3ea
Compare
faresobeid
marked this pull request as ready for review
October 7, 2026 13:34
Processes sharing ~/.triton on a shared FS hang or crash. Add TRITON_CACHE_DIR=/tmp/triton-<uid> to DEFAULT_COMMON_ENV_VARS so every launched component gets it; env_vars in the config override it.
faresobeid
force-pushed
the
fix/triton-cache-node-local
branch
from
October 7, 2026 19:23
ff9d3ea to
f435bc5
Compare
mikasenghaas
reviewed
Oct 7, 2026
Signed-off-by: faresobeid <111092724+faresobeid@users.noreply.github.com>
mikasenghaas
approved these changes
Oct 8, 2026
faresobeid
added a commit
that referenced
this pull request
Oct 11, 2026
## What - `VLLM_CACHE_ROOT=/tmp/.vllm-cache-<uid>` and `FLASHINFER_WORKSPACE_BASE=/tmp/.flashinfer-cache-<uid>` are added to `DEFAULT_INFERENCE_ENV_VARS`. `TRITON_CACHE_DIR` got the same treatment in #3877. - The by-hand copies (`/tmp/.vllm-cache`, `/tmp/.flashinfer-cache`) are removed from the four GLM-4.5-Air recipes. Those paths were shared by every user on a node. - docs/scaling.md gets one paragraph that lists the node-local cache defaults. The paths are dot-prefixed so the SLURM start-up cleanup (`rm -rf /dev/shm/vllm-* /dev/shm/vllm_* /tmp/vllm-* /tmp/vllm_* /tmp/torch-* /tmp/torchelastic_*` in the multi_node_rl, multi_node_sft and inference sbatch templates) does not wipe them. These are the same names the recipes used before. Precedence is the same as for the other launcher defaults: `[env_vars]` or `[inference.env_vars]` override them; a value exported in the shell does not. ## Why - Without these, vLLM's AOT/Inductor compile cache lives in `~/.cache/vllm` and FlashInfer's JIT cache under `$HOME`, which is usually the shared filesystem. - Measured while testing #3877 (GLM-4.5-Air TP8, vLLM 0.31): a crashed start left a partial shared vLLM cache. On the next start, 4 TP ranks loaded those artifacts and the other 4 recompiled. The ranks diverged and hung in a collective. So one crash breaks every later start that uses that cache. - The original scaleswe recipe (#2862) moved this cache to `/tmp` because the NFS cache hung inference startup. - Cost: the first start on each new node has a cold vLLM cache. GLM-4.5-Air: 465 s cold vs 375 s with a warm vLLM cache, so about 1.5 min once per node. ## Overlap - #3627 (garrett361, draft) adds `VLLM_CACHE_ROOT`/`FLASHINFER_WORKSPACE_BASE` under `/tmp/garrett/` to new DeepSeek-V4 recipes. With this PR those lines can go. ## Test plan - `pytest tests/unit/orchestrator tests/unit/test_configs.py tests/unit/utils -m "not gpu"`: 365 passed (rebased on origin/main 41a8ed0). - Ran the cleanup globs in a scratch dir that held `.vllm-cache-<uid>`, `.flashinfer-cache-<uid>` and, as a control, `vllm-cache-<uid>`. Only the control matched. - `ruff check` and `ruff format --check` on `process.py`: clean. - `rl @ examples/advanced/glm-4.5-air/swe.toml --dry-run`: - The rendered `rl.sbatch` exports both vars only in the inference block (`/tmp/.vllm-cache-<uid>`, `/tmp/.flashinfer-cache-<uid>`). - With `--inference.env-vars '{"VLLM_CACHE_ROOT": "/scratch/vc"}'`, the sbatch exports `/scratch/vc`. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Launcher default env vars for inference only; configs can still override, with no auth or training logic changes. > > **Overview** > Inference launches now default **vLLM** and **FlashInfer** compile/JIT caches to per-user paths under `/tmp` (`VLLM_CACHE_ROOT`, `FLASHINFER_WORKSPACE_BASE`), matching the existing Triton cache behavior and avoiding shared `$HOME` or NFS caches that can leave tensor-parallel ranks on mismatched artifacts and hang. > > The four GLM-4.5-Air example recipes drop redundant `[inference.env_vars]` blocks that duplicated those settings. **docs/scaling.md** documents the launcher defaults and notes overrides via `[env_vars]` or component `env_vars`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit fe8a34d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
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.
Processes that share
~/.tritonon a shared filesystem can hang or crash (seen with Nemotron-H, where many ranks compile the Mamba Triton kernels at once; reproduced below with Qwen3.5 and GLM-4.5-Air).This PR adds
TRITON_CACHE_DIR = /tmp/triton-<uid>toDEFAULT_COMMON_ENV_VARS. It is per-user because/tmpis shared by all users on a node. Like the other launcher defaults, it reaches every launched component: the localrl/sft/inferencelaunchers (also used by the single-node sbatch scripts) and the trainer, orchestrator, inference (incl. prefill/decode), and online-eval env blocks of the multi-node and inference sbatch scripts.[env_vars](or a component'senv_vars) overrides it; a value exported in the shell or.envdoes not. It also removes theTRITON_CACHE_DIRoverrides from six example configs (glm-4.5-air swe/swe-budget/search/terminal, glm-5.3 and qwen3-30b-a3b sft h200 base): they pointed every user at the same/tmpdir and are now covered by the default.docs/scaling.mdsays so in one paragraph.vLLM 0.31's own default: when
TRITON_CACHE_DIRis unset, its Inductor adaptor points it at$VLLM_CACHE_ROOT/torch_compile_cache/<hash>/rank_<i>_<j>/triton_cache(~/.cache/vllmby default, so usually on the shared home). That only covers Triton kernels compiled after torch.compile initializes, and it is still on the shared filesystem. vLLM keeps aTRITON_CACHE_DIRthat is already set, so with this PR vLLM uses/tmp/triton-<uid>too.Measured cost (one H200 node, vLLM 0.31 venv, Triton 3.7.1)
Each run starts from a fresh process with the same config. "Ready" is launch → first trainer step logged (Qwen) or launch →
/healthOK (GLM). For GLM, the first generated token came 1.3–2 s after ready in every run that came up. Inductor's cache dir was emptied before each run except the warm node-local one.FileNotFoundErroron a cache file that another rank was writing (causal_conv1d_fwd_kernel.llir,l2norm_fwd_kernel.ptx)FileNotFoundErrorin the cache during Inductor autotune, the other 4 hung in a collective until killed (1st run). The 2nd run crashed instead of hanging.VLLM_CACHE_ROOT(~/.cache/vllm, shared home) holds vLLM's AOT/Inductor artifacts. With this PR it stays shared. On a new node, vLLM loads those artifacts (torch.compile0.6 s instead of 30 s), and the Triton binaries are compiled into/tmp/triton-<uid>(106 kernels, +31 s).TORCHINDUCTOR_CACHE_DIR(default/tmp/torchinductor_<user>, already node-local) stayed empty in these runs. Inductor's Triton kernels go toTRITON_CACHE_DIR.Possible middle ground (not implemented)
Because the cold cost is above 1 min per node for FLA-heavy models, a run could seed the node-local cache from a shared read-only copy at job start. For example, on each node before the components start:
[ -n "$TRITON_CACHE_SEED" ] && cp -rn "$TRITON_CACHE_SEED"/. "$TRITON_CACHE_DIR"/The seed would be a warm
/tmp/triton-<uid>copied once to the shared FS. Triton keys entries by source, compiler, and GPU, so stale entries are never reused, only skipped. Only reads hit the shared FS, so the concurrent-write race does not occur. I left it out to keep this PR minimal.Note
Low Risk
Launch-time env default only; behavior is overridable via config and fixes known multi-rank Triton cache races, with a one-time cold-compile cost on each node.
Overview
Sets a global launcher default so every trainer, orchestrator, and inference process gets
TRITON_CACHE_DIR=/tmp/triton-<uid>viaDEFAULT_COMMON_ENV_VARS, avoiding concurrent Triton kernel writes under~/.tritonon a shared filesystem (hangs /FileNotFoundErrorunder multi-rank compile).Removes redundant
[env_vars]overrides from six GLM-4.5-Air RL and GLM-5.3 / Qwen3-30B SFT example configs that previously pinned Triton cache paths under/tmp; those runs now inherit the per-user node-local default (still overridable through configenv_vars).Reviewed by Cursor Bugbot for commit f216420. Bugbot is set up for automated code reviews on this repo. Configure here.