PeriodicBlockStepper.step: mid-batch launch failure test; async-error docstring note
Review follow-up (non-blocking items): a launch failure on the second of three steps fails closed without the batch wait, keeps step_count at its entry value and blocks download; the docstring now states, as for FixedPatchStepper, that async faults surface at the single wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3648ad70ef
commit
f3f1e3d588
2 files changed
+24
-2
No files matched your search
@@ -207,8 +207,11 @@ class PeriodicBlockStepper:
|
|||||||
"""Advance n steps: halo refresh, then core pull/collide, per step.
|
"""Advance n steps: halo refresh, then core pull/collide, per step.
|
||||||
|
|
||||||
All n steps are enqueued in order on the one stream and the host waits
|
All n steps are enqueued in order on the one stream and the host waits
|
||||||
once before returning (same launches and bits as n step(1) calls). On a
|
once before returning (same launches and bits as n step(1) calls).
|
||||||
failure the instance is failed and step_count keeps its entry value.
|
Asynchronous device errors surface at that single wait, so they are not
|
||||||
|
attributed to the step that caused them; call step(1) repeatedly to
|
||||||
|
localize one. On any failure the instance is failed and step_count keeps
|
||||||
|
its entry value.
|
||||||
"""
|
"""
|
||||||
if isinstance(n, bool) or not isinstance(n, Integral) or n < 0:
|
if isinstance(n, bool) or not isinstance(n, Integral) or n < 0:
|
||||||
raise ValueError("n must be a nonnegative integer")
|
raise ValueError("n must be a nonnegative integer")
|
||||||
|
|||||||
@@ -78,6 +78,25 @@ class BlockStepSync(unittest.TestCase):
|
|||||||
run.step(2)
|
run.step(2)
|
||||||
self.assertEqual((run.step_count, run._status), (1, "failed"))
|
self.assertEqual((run.step_count, run._status), (1, "failed"))
|
||||||
|
|
||||||
|
def test_launch_failure_mid_batch_fails_closed_without_waiting(self):
|
||||||
|
run, log = backend()
|
||||||
|
calls = []
|
||||||
|
step = run._step
|
||||||
|
|
||||||
|
def failing(*args, **kwargs):
|
||||||
|
calls.append(1)
|
||||||
|
if len(calls) == 2:
|
||||||
|
raise RuntimeError("launch failure")
|
||||||
|
return step(*args, **kwargs)
|
||||||
|
|
||||||
|
run._step = failing
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
run.step(3)
|
||||||
|
self.assertNotIn("sync", [name for name, _ in log])
|
||||||
|
self.assertEqual((run.step_count, run._status), (0, "failed"))
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
run.download()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
Reference in new issue
Block a user