DataLoader timeout limits: worker processes persist after RuntimeError
0 reputation · 09 Jun 2020, 10:54 UTC
0 reputation · 09 Jun 2020, 10:54 UTC
torch.utils.data.DataLoader exposes a documented timeout argument that bounds how long the main process waits for a batch from worker processes when num_workers is greater than zero. Exceeding this limit raises a RuntimeError in the main process, but the timeout does not transmit a cancellation signal to the worker itself. The worker process and any in-flight __getitem__ operation continue executing, and the DataLoader is left in an undefined state with no automatic worker replacement.
Because the library provides no supported API to cancel a specific stuck worker or reset the loader cleanly, the timeout functions only as a main-process wait limit rather than a lifecycle control. Should a timeout be treated as a hard failure requiring full loader teardown, or is there a documented pattern for isolating and replacing only the affected worker? What is the expected behavior of subsequent iteration on the same DataLoader instance after a timeout fires?
35775 reputation · 09 Jun 2020, 11:11 UTC
A DataLoader timeout is a main-process wait limit only. When it fires, PyTorch raises RuntimeError in the main process but sends no cancellation signal to the worker. The stuck __getitem__ and its worker process continue running. There is no supported API to interrupt a single worker, replace only that worker, or reset the loader’s iteration state cleanly.
Treat the timeout as a hard failure for that DataLoader instance. Stop iteration, discard the loader, and create a new one (which spawns a fresh worker pool). Do not call __iter__ or next() again on the same instance.
The timeout argument is implemented as a deadline on the internal queue get() that the coordinator thread uses to fetch the next batch. It is not a worker lifecycle controller. When the deadline expires, the coordinator raises RuntimeError and abandons the queue read; the worker process remains alive, still executing the slow __getitem__ or blocked on I/O, locks, or GPU operations.
Behavior is undefined and version-dependent. Observed outcomes include:
next() hangs indefinitely waiting for a result that will never arrive.persistent_workers=True makes stuck workers more visible across epochs but does not add per-worker cancellation.RuntimeError (or the specific torch.utils.data._utils.worker.TimeoutError subclass if available in your version).DataLoader reference and, if practical, call torch.utils.data._utils.worker._worker_loop cleanup helpers—though the only reliable path is to let the process exit or recreate the loader in a fresh process.DataLoader with the same configuration to get a clean worker pool.What multiprocessing start method are you using (fork, spawn, or forkserver) and what PyTorch version? Cleanup semantics (whether __del__ terminates workers, how queues are drained, and whether persistent_workers interacts with timeout) differ across these combinations. If you are on spawn or forkserver with a recent PyTorch (≥2.1), worker teardown on loader deletion is more deterministic, but the no-single-worker-replacement rule still holds.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.