Skip to content

Commit 096534d

Browse files
authored
Merge pull request #3183 from bghira/bugfix/3176
Improve CUDA OOM log extraction
2 parents 286c6a6 + f6fb221 commit 096534d

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

simpletuner/simpletuner_sdk/process_keeper.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@
3535
lock = threading.Lock()
3636

3737

38+
def _is_cuda_oom_log_line(lowered: str) -> bool:
39+
return (
40+
"torch.cuda.outofmemoryerror" in lowered
41+
or "cuda out of memory" in lowered
42+
or "memory mapping failed with oom" in lowered
43+
)
44+
45+
3846
class TrainerProcess:
3947
"""Wrapper for a training subprocess with IPC communication."""
4048

@@ -744,7 +752,7 @@ def _extract_error_from_logs(self, exit_code: Optional[int]) -> Optional[Dict[st
744752
preferred_message: Optional[str] = None
745753
for line in reversed(tail_lines):
746754
lowered = line.lower().strip()
747-
if "cuda out of memory" in lowered:
755+
if _is_cuda_oom_log_line(lowered):
748756
preferred_message = line.strip()
749757
break
750758
if "childfailederror" in lowered:

tests/test_process_keeper.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,35 @@ def test_log_extraction_prefers_cuda_oom_message(self):
344344
self.fail("Expected payload from log extraction")
345345
self.assertIn("CUDA out of memory", payload.get("message", ""))
346346

347+
def test_log_extraction_prefers_allocator_oom_over_aoti_error(self):
348+
"""Allocator OOM warnings should beat generic compiled-kernel RuntimeErrors."""
349+
job_id = "test_log_allocator_oom"
350+
process = TrainerProcess(job_id)
351+
352+
with tempfile.TemporaryDirectory() as tmpdir:
353+
log_path = os.path.join(tmpdir, "stdout.log")
354+
with open(log_path, "w", encoding="utf-8") as handle:
355+
handle.write("starting epoch 5\n")
356+
handle.write(
357+
"[W831 10:32:25.255074645 CUDACachingAllocator.cpp:508] "
358+
"expandable_segments: memory mapping failed with OOM on device 0 while trying to map 20971520 bytes.\n"
359+
)
360+
handle.write("Traceback (most recent call last):\n")
361+
handle.write(
362+
"RuntimeError: aoti_torch_empty_strided(3, int_array_74, int_array_75, "
363+
"cached_torch_dtype_bfloat16, cached_torch_device_type_cuda, 0, &buf80_handle) API call failed\n"
364+
)
365+
366+
process.log_file = log_path
367+
payload = process._extract_error_from_logs(exit_code=1)
368+
369+
self.assertIsNotNone(payload)
370+
if payload is None:
371+
self.fail("Expected payload from log extraction")
372+
message = payload.get("message", "")
373+
self.assertIn("memory mapping failed with OOM", message)
374+
self.assertNotIn("aoti_torch_empty_strided", message)
375+
347376
def test_log_extraction_prefers_signal_exit(self):
348377
"""Synthetic log extraction should highlight signal-based exits."""
349378
job_id = "test_log_signal_exit"

0 commit comments

Comments
 (0)