Skip to content

osdc/hf-cache: raise 1-GPU rclone reserve to 1Gi - #890

Closed
huydhn wants to merge 1 commit into
pytorch:mainfrom
huydhn:hf-cache-gpu1-1gi
Closed

osdc/hf-cache: raise 1-GPU rclone reserve to 1Gi#890
huydhn wants to merge 1 commit into
pytorch:mainfrom
huydhn:hf-cache-gpu1-1gi

Conversation

@huydhn

@huydhn huydhn commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What

Raise the hf-cache-mount-gpu1 rclone memory tier 512Mi → 1Gi, and trim the three single-GPU runner defs (arc-runners + arc-runners-opt) to fit under the larger request == limit reserve.

Why

#883 tiered rclone memory by GPU count and gave the 1-GPU tier 512Mi. But under --vfs-cache-mode full, rclone RSS tracks the model files a job reads, not GPU count — and 1-GPU a10g nodes run the inductor_huggingface suite, which loads the largest models. rclone crosses 512Mi → OOMKilled → the node-wide /mnt/hf_cache FUSE mount dies → the job's mmap'd safetensors read faults with SIGBUS (Run failed with return code: -7), which surfaces as a misleading LocalEntryNotFoundError ("missing weights"). 1Gi restores the floor these nodes ran at before #883.

Evidence

Live rclone OOMs, both prod clusters, gpu1 tier only (cpu/gpu4/gpu8 = 0):

  • meta-prod-aws-ue2: 17/59 mounts OOMKilled
  • meta-prod-aws-ue1: 9/80 OOMKilled

Flaky because the OOM only trips when rclone crosses 512Mi mid-load — same job, same ue1 bucket:

  • fail: pytorch/pytorch runs/29433922962/job/87421947313 (Loading weights: 25%|…| 36/146 … return code: -7)
  • pass: pytorch/pytorch runs/29436575323/job/87456375877

The file isn't missing (the load reached 25% of 146 shards); the LocalEntryNotFoundError is a retry cascade after the SIGBUS.

Runner trims (label keeps -NNN-)

  • a10g g5.8xlarge / l4 g6.8xlarge: 113 → 112Gi
  • t4 g4dn.8xlarge: 115 → 114Gi

Deploy

Redeploy hf-cache + arc-runners (+arc-runners-opt) to the clusters running these 1-GPU classes.

The 1-GPU tier reserved only 512Mi for rclone (pytorch#883). rclone RSS under
`--vfs-cache-mode full` is driven by the model files a job reads, not by GPU
count, so a single-GPU inductor job OOM-kills rclone at 512Mi, dropping the
node-wide `/mnt/hf_cache` FUSE mount → job pods fail with `CreateContainerError`.

Observed on a g5.8xlarge (1x a10g):
https://github.com/pytorch/pytorch/actions/runs/29042231396/job/86206746830

Raise the `hf-cache-mount-gpu1` tier 512Mi → 1Gi (the previously-working
pre-pytorch#883 floor). The reserve is `request == limit`, so trim the untrimmed
1-GPU runner defs to keep them schedulable (`analyze-utilization` confirms
1 pod/node): a10g/l4 (g5/g6.8xlarge) 113→112Gi, t4 (g4dn.8xlarge) 115→114Gi.
Labels keep their `-NNN-`. Packing overhead (daemonset_overhead) tier updated.

Deploy: redeploy hf-cache + arc-runners (+arc-runners-opt) to the clusters
running these 1-GPU classes.
@huydhn
huydhn marked this pull request as ready for review July 9, 2026 23:02
@huydhn
huydhn requested a review from jeanschmidt as a code owner July 9, 2026 23:02
@jeanschmidt

Copy link
Copy Markdown
Contributor

lets pause on this, as I believe this can be a problem to CPU on -opt fleet

@jeanschmidt jeanschmidt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should reduce the memory usage, not raise memory for the pod

@jeanschmidt

Copy link
Copy Markdown
Contributor

we can SUBSTANTIALLY reduce memory usage, without significant performance drop, potentially to 128Mib.

rclone is a go binary, and we can easily control go GC behavior and memory footprint without requiring infinite memory. The problem here is GC, NOT how much memory the process requires.

few knobs:

  • --buffer-size - per file buffer size
  • --max-buffer-memory - total memory we can use for buffering
  • GOMEMLIMIT / GOGC - Set this to a few MiB lower than the total memory available, this will tell GO VM when it should pause and run a GC, over infinite piling memory

@jeanschmidt

Copy link
Copy Markdown
Contributor

with this, we can probably get rid of the stagger multi-size memory we set up for GPUs

huydhn added a commit to huydhn/pytorch-ci-infra that referenced this pull request Jul 10, 2026
rclone is a Go binary. Its OOMs on high-concurrency GPU nodes are a GC problem,
not a genuine memory requirement: under bursty `--vfs-cache-mode full` buffering
the Go heap grows past the container's cgroup limit before the GC runs, and the
kernel OOM-kills the process — dropping the `/mnt/hf_cache` FUSE mount node-wide
(dead mount → job-pod CreateContainerError).

Give the runtime a soft memory ceiling at 90% of the container limit so the GC
reclaims buffering before the kernel intervenes. The limit is injected in bytes
via the downward API (`RCLONE_MEMORY_LIMIT_BYTES` ← `limits.memory`) and the
launch script exports `GOMEMLIMIT` before starting rclone (Go reads it once at
startup), so it tracks whatever per-tier reservation deploy.sh renders — no new
placeholder, no hard-coded value.

This targets the OOM at the *current* per-tier limits (256Mi–4Gi) rather than
raising them (cf. pytorch#890). Follow-up levers Jean noted, to validate against the
deployed rclone version before adding: `--buffer-size` (per-file buffer) and
`--max-buffer-memory` (global buffer cap).

Deploy: redeploy hf-cache.
huydhn added a commit to huydhn/pytorch-ci-infra that referenced this pull request Jul 10, 2026
rclone is a Go binary. Its OOMs on high-concurrency GPU nodes are a GC problem,
not a genuine memory requirement: under bursty `--vfs-cache-mode full` buffering
the Go heap grows past the container's cgroup limit before the GC runs, and the
kernel OOM-kills the process — dropping the `/mnt/hf_cache` FUSE mount node-wide
(dead mount → job-pod CreateContainerError).

Give the runtime a soft memory ceiling at 90% of the container limit so the GC
reclaims buffering before the kernel intervenes. The limit is injected in bytes
via the downward API (`RCLONE_MEMORY_LIMIT_BYTES` ← `limits.memory`) and the
launch script exports `GOMEMLIMIT` before starting rclone (Go reads it once at
startup), so it tracks whatever per-tier reservation deploy.sh renders — no new
placeholder, no hard-coded value.

This targets the OOM at the *current* per-tier limits (256Mi–4Gi) rather than
raising them (cf. pytorch#890). Follow-up levers Jean noted, to validate against the
deployed rclone version before adding: `--buffer-size` (per-file buffer) and
`--max-buffer-memory` (global buffer cap).

Deploy: redeploy hf-cache.
@huydhn

huydhn commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Closing this as I haven't seen OOM for a couple of days, so I would assume that the GOMEMLIMIT fix does the trick

@huydhn huydhn closed this Jul 14, 2026
@huydhn huydhn reopened this Jul 16, 2026
huydhn added a commit to huydhn/pytorch-ci-infra that referenced this pull request Jul 16, 2026
…ch#907)

## Problem
On the 1-GPU mount tier (512Mi), concurrent large-model (safetensors)
reads OOM-kill rclone → the node-wide `/mnt/hf_cache` FUSE mount dies →
the job's mmap'd read faults with **SIGBUS**, surfacing as a misleading
`LocalEntryNotFoundError` ("missing weights").

Example — failing `inductor_huggingface` a10g job:
```
Loading weights: 25%|██▍| 36/146 … Run failed with return code: -7   # SIGBUS
huggingface_hub.errors.LocalEntryNotFoundError: Cannot find the requested files in the disk cache ...
```
Stats — live rclone `OOMKilled` mounts, **gpu1 tier only**
(cpu/gpu4/gpu8 = 0): ue2 **17/59**, ue1 **9/80**.

## Fix
rclone RSS under `--vfs-cache-mode full` is dominated by per-open-file
read-ahead buffers, not GPU count:
- `--buffer-size 4M` — 4x cut from rclone's 16Mi-per-open-file default
read-ahead (the RSS driver when a model opens many shards); kept
non-zero so cold reads retain some prefetch, with the on-disk cache
serving the rest.
- `--use-mmap` — return freed buffers to the OS instead of Go retaining
them as RSS.

Keeps rclone inside the reserve without raising the limit. Complements
pytorch#890 (512Mi→1Gi headroom).
@huydhn

huydhn commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Not need this anymore

@huydhn huydhn closed this Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants