refinement: free-memory preflight for every level before any device work

Restores the PeriodicBlockStepper safeguard dropped in 8e1feff, for all
FixedPatchStepper levels: both G buffers, halo pairs and boundary columns
of every level are compared with cuda.mem_get_info() before the stream,
any module or any buffer exists, raising MemoryError('level buffers exceed
free device memory'). Transfer tables are not counted (lower bound).

Tests: the single-level MemoryError case is back beside the param-layout
check (no stream, no allocation); host test_single_level covers depth 1
and depth 2 (no stream, build or allocation) and the wait failure after a
good step (count stays 1). Driver-mocking fixtures report ample free memory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-27 01:10:15 +00:00
1 parent 8c776309c9
commit 19db7d362f
9 files changed
+57 -8

No files matched your search

@@ -122,7 +122,7 @@ class BlockedFineCPU(unittest.TestCase):
raise AssertionError("zero-byte device allocation")
sizes.append(size)
return Mock()
with patch.object(cuda, "Stream"), patch.object(compiler, "generate_config"), \
with patch.object(cuda, "Stream"), patch.object(cuda, "mem_get_info", return_value=(1 << 40, 1 << 40)), patch.object(compiler, "generate_config"), \
patch.object(compiler, "compile_kernel"), patch.object(compiler, "cleanup_build_dir"), \
patch.object(compiler, "load_module", return_value=module), \
patch.object(cuda, "mem_alloc", side_effect=alloc), patch.object(cuda, "memcpy_htod"):
@@ -172,7 +172,7 @@ class BlockedFineCPU(unittest.TestCase):
return functions.setdefault(name, Mock(side_effect=lambda *a, **k: calls.append((name, a))))
module = Mock(get_function=Mock(side_effect=get_function))
module.get_global.return_value = (Mock(), 20)
with patch.object(cuda, "Stream"), patch.object(compiler, "generate_config"), \
with patch.object(cuda, "Stream"), patch.object(cuda, "mem_get_info", return_value=(1 << 40, 1 << 40)), patch.object(compiler, "generate_config"), \
patch.object(compiler, "compile_kernel"), patch.object(compiler, "cleanup_build_dir"), \
patch.object(compiler, "load_module", return_value=module), \
patch.object(cuda, "mem_alloc", side_effect=lambda size: Mock()), \