Share RAM image caches across DataLoader workers - #26086
Conversation
|
👋 Hello @glenn-jocher, thank you for submitting a
For more guidance, please refer to our Contributing Guide. Don't hesitate to leave a comment if you have any questions. Thank you for contributing to Ultralytics! 🚀 |
UltralyticsAssistant
left a comment
There was a problem hiding this comment.
🔍 PR Review
Made with ❤️ by Ultralytics Actions
Reviewed the shared cache owner, detection load_image path, and classification integration. The private-copy semantics and reuse of the loaded image are coherent, but the new shared-buffer allocation introduces an unhandled constrained-storage failure path. Not LGTM until allocation is validated or fails safely.
💬 Posted 1 inline comment
- 💡 MEDIUM
ultralytics/data/base.py:81RawArraycan use a limited shared-memory or temporary-file backing store, but the existing preflight only checkspsutil.virtual_memory().available(andClassificationDatasetdoes not preflight at all). On macOS or Linux with constrained/dev/shm/temporary storage,cache='ram'can pass validation and then fail here with an allocation error or exhaust the backing filesystem during dataset construction. Add an owner-level resource check with a safe uncached fallback, covering both detect…
| self.dtypes = np.array([im.dtype.str for im in images]) | ||
| self.offsets = np.concatenate(([0], np.cumsum([im.nbytes for im in images]))) | ||
| self.buffer = np.empty(self.offsets[-1], dtype=np.uint8) | ||
| self.buffer = RawArray("B", int(self.offsets[-1])) |
There was a problem hiding this comment.
💡 MEDIUM: RawArray can use a limited shared-memory or temporary-file backing store, but the existing preflight only checks psutil.virtual_memory().available (and ClassificationDataset does not preflight at all). On macOS or Linux with constrained /dev/shm/temporary storage, cache='ram' can pass validation and then fail here with an allocation error or exhaust the backing filesystem during dataset construction. Add an owner-level resource check with a safe uncached fallback, covering both detection and classification paths.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Follow-up design review and handoffReviewed head: Better candidate to investigateReplace the existing packed NumPy pixel buffer with a packed CPU Torch uint8 tensor, and use NumPy views when retrieving images. Investigate relying on PyTorch multiprocessing storage reducers to establish sharing only when a dataset is serialized for spawn/forkserver workers, rather than allocating shared backing unconditionally. The intended benefit is to preserve ordinary RAM/copy-on-write behavior for zero-worker and fork loaders while avoiding a full pixel-cache copy per spawned worker. This is a proposal, not a validated drop-in fix. Verify the reducer behavior and lifetime on supported platforms and the Python/PyTorch support floor before relying on it. Independent distributed-training ranks are outside this sharing scope. Blockers and design constraints
Next steps / acceptance evidence
Related context: PyTorch #13246 describes longstanding worker memory replication; Ultralytics #9824 and merged #24670/#24673 cover earlier cache improvements, while #24364 explored shared tensor storage. Recheck their exact scope rather than assuming they prove this proposal. These are memory/reliability concerns; no verified security advisory is established here. Claude Code Fable 5.1 (high) recommends investigating the Torch-storage approach, but it has not been implemented or validated and is not yet LGTM. |
Scope
Extract only the RAM image-cache change from #26085 so it can be evaluated independently. This PR does not change DataLoader multiprocessing defaults, pinning, worker lifecycle, or model behavior. It does not fix the fork deadlock investigated in #26085.
The existing contiguous NumPy cache benefits from fork copy-on-write, but spawn/forkserver can serialize the full pixel buffer into each worker. Replace that buffer at the existing
BaseDataset._ImageCacheowner withmultiprocessing.RawArray, shared by detection-family and classification datasets. Return private per-image copies before transforms, and reuse the image already retrieved inload_imageto avoid copying twice.Related history and boundaries
The linked reports establish longstanding memory/reliability problems. No verified security advisory or CVE is asserted here.
Validation
Prior isolated tests of these exact cache-file changes, carried over from #26085:
Fresh checks on this cache-only branch: eight-worker macOS spawn sharing check, three existing dataloader tests, changed-code lint and diff whitespace checks.
Draft blockers
This is a separation for focused review, not a claim of LGTM. The previous Fable 5.1/high review identified concerns still applicable to this extracted implementation:
RawArraycan fall back from/dev/shmto temporary disk backing, and macOS uses temporary disk backing. The existing RAM budget check does not account for this storage requirement. Constrained storage and allocation failure need a safe design and validation before this is ready.The global Linux forkserver compatibility objections from #26085 do not apply to this diff because it leaves the start method unchanged. A fresh independent Fable 5.1/high review remains required once the cache implementation is ready.