import%20marimo%0A%0A__generated_with%20%3D%20%220.19.9%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20%23%20Shared%20imports%20for%20the%20notebook%0A%20%20%20%20import%20random%0A%20%20%20%20from%20monarch.actor%20import%20Actor%2C%20endpoint%2C%20current_rank%2C%20MeshFailure%2C%20this_host%0A%0A%20%20%20%20return%20Actor%2C%20MeshFailure%2C%20endpoint%2C%20this_host%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Fault%20Tolerance%20in%20Monarch%0A%0A%20%20%20%20In%20the%20last%20notebook%2C%20you%20caught%20a%20single%20error%20with%20try%2Fexcept%20on%20a%0A%20%20%20%20FlakyWorker.%20That%20works%20when%20you%20know%20which%20actor%20failed%20and%20have%20a%20backup%0A%20%20%20%20ready.%20But%20when%20failures%20hit%20every%203%20hours%20across%2016%2C000%20GPUs%2C%20you%20need%0A%20%20%20%20patterns%20that%20scale.%0A%0A%20%20%20%20This%20notebook%20covers%20three%20layers%20of%20fault%20handling%0A%0A%20%20%20%201.%20**Try%2Fexcept%20with%20retry**%20%E2%80%94%20the%2090%25%20solution%20you'll%20reach%20for%20first%0A%20%20%20%202.%20**Supervision%20trees**%20%E2%80%94%20centralized%20error%20surfacing%20for%20infrastructure%20builders%0A%20%20%20%203.%20**TorchFT**%20%E2%80%94%20quorum-based%20training%20that%20continues%20through%20failures%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20The%20Supervision%20Tree%0A%0A%20%20%20%20Large%20scale%20training%20will%20run%20into%20issues%20with%20faulty%20hardware%2C%20flaky%20networks%2C%20and%0A%20%20%20%20software%20bugs.%20Monarch%20is%20designed%20to%20provide%20good%20behaviors%20for%20errors%20and%20faults%20by%0A%20%20%20%20default%20with%20the%20option%20to%20define%20more%20sophisticated%20behavior%20for%20faster%20recovery%20or%0A%20%20%20%20fault%20tolerance.%0A%0A%20%20%20%20We%20borrow%20from%20Erlang%20the%20idea%20of%20a%20tree%20of%20supervision.%20Each%20process%2C%20and%20each%20actor%0A%20%20%20%20has%20a%20parent%20that%20launched%20it%20and%20is%20responsible%20for%20its%20health.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Actor%2C%20endpoint)%3A%0A%20%20%20%20from%20monarch.actor%20import%20this_proc%0A%0A%20%20%20%20class%20Errorful(Actor)%3A%0A%20%20%20%20%20%20%20%20%40endpoint%0A%20%20%20%20%20%20%20%20def%20say_hello(self)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20Exception(%22I%20don't%20want%20to%22)%0A%0A%20%20%20%20e%20%3D%20this_proc().spawn(%22errorful%22%2C%20Errorful)%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20e.say_hello.call_one().get()%0A%20%20%20%20except%20Exception%3A%0A%20%20%20%20%20%20%20%20print(%22It%20didn't%20say%20hello%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20If%20we%20are%20calling%20the%20endpoint%20and%20expecting%20a%20response%2C%20the%20error%20gets%20routed%20to%0A%20%20%20%20the%20caller.%20But%20we%20might%20also%20call%20something%20and%20provide%20it%20no%20way%20to%20respond%20%E2%80%94%20in%0A%20%20%20%20that%20case%20the%20error%20will%20be%20delivered%20to%20the%20owner%20of%20the%20actor%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20e.say_hello.broadcast()%20%20%23%20do%20not%20expect%20a%20response%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20The%20default%20behavior%20of%20the%20supervision%20tree%20means%20that%20an%20error%20at%20any%20level%20of%20process%0A%20%20%20%20or%20actor%20creation%20will%20not%20go%20unreported.%20This%20can%20prevent%20a%20lot%20of%20accidental%20deadlocks%0A%20%20%20%20compared%20to%20the%20standard%20unix-style%20defaults%20where%20threads%20and%20processes%20exiting%20do%20not%0A%20%20%20%20stop%20the%20spawning%20processes.%0A%0A%20%20%20%20%23%23%23%20Fine-grained%20Supervision%0A%0A%20%20%20%20Sometimes%20fine-grained%20recovery%20is%20possible.%20For%20instance%2C%20if%20a%20data%20loader%20failed%20to%0A%20%20%20%20read%20a%20URL%2C%20perhaps%20it%20would%20work%20to%20just%20restart%20it.%20If%20an%20actor%20defines%20a%20%60__supervise__%60%0A%20%20%20%20special%20method%2C%20then%20it%20will%20get%20called%20to%20handle%20supervision%20events%20for%20meshes%20owned%20by%0A%20%20%20%20the%20actor.%20If%20an%20error%20happens%20on%20an%20ActorMesh%20that%20is%20a%20reference%2C%20such%20as%20a%20slice%2C%20or%20a%0A%20%20%20%20mesh%20that%20is%20sent%20to%20another%20actor%2C%20then%20the%20recovery%20is%20done%20on%20the%20original%20creator%20of%0A%20%20%20%20that%20mesh%2C%20not%20the%20holder%20of%20the%20reference.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Actor%2C%20MeshFailure)%3A%0A%20%20%20%20import%20monarch.actor%0A%0A%20%20%20%20class%20SupervisorActor(Actor)%3A%0A%20%20%20%20%20%20%20%20def%20__supervise__(self%2C%20failure%3A%20MeshFailure)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Failure%20received%3A%20%7Bfailure%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20If%20a%20truthy%20value%20is%20returned%2C%20the%20supervision%20event%20is%20considered%20handled%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20and%20will%20not%20be%20propagated%20further.%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Otherwise%2C%20the%20event%20will%20be%20propagated%20to%20the%20creator%20of%20this%20actor.%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20True%0A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20If%20a%20%60MeshFailure%60%20is%20not%20handled%20by%20any%20%60__supervise__%60%20in%20the%20supervision%20tree%2C%20it%20will%0A%20%20%20%20reach%20the%20client%2C%20where%20%60monarch.actor.unhandled_fault_hook%60%20will%20be%20called%20with%20the%0A%20%20%20%20%60MeshFailure%60%20object.%20By%20default%2C%20this%20function%20crashes%20the%20client%20process%20with%20exit%20code%201.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MeshFailure)%3A%0A%20%20%20%20import%20monarch.actor%20as%20_monarch_actor%0A%0A%20%20%20%20def%20my_unhandled_fault_hook(failure%3A%20MeshFailure)%20-%3E%20None%3A%0A%20%20%20%20%20%20%20%20print(f%22Mesh%20failure%20was%20not%20handled%3A%20%7Bfailure%7D%22)%0A%0A%20%20%20%20_monarch_actor.unhandled_fault_hook%20%3D%20my_unhandled_fault_hook%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Supervision%20Trees%3A%20Centralized%20Error%20Surfacing%0A%0A%20%20%20%20Try%2Fexcept%20works%20when%20the%20**caller**%20catches%20failures.%20But%20what%20about%20failures%0A%20%20%20%20you%20don't%20directly%20trigger%20%E2%80%94%20a%20child%20actor%20crashing%20in%20the%20background%2C%20a%0A%20%20%20%20cascading%20failure%20deep%20in%20a%20hierarchy%3F%0A%0A%20%20%20%20Monarch's%20answer%20is%20the%20__supervise__%20API.%20When%20an%20actor%20spawns%20children%2C%20it%20becomes%0A%20%20%20%20their%20supervisor.%20If%20a%20child%20fails%2C%20the%20supervisor's%20%60__supervise__%60%20method%20is%0A%20%20%20%20called%20with%20a%20%60MeshFailure%60%20describing%20what%20went%20wrong.%0A%0A%20%20%20%20Think%20of%20it%20like%20a%20management%20chain%3A%20when%20an%20employee%20hits%20a%20problem%20they%20can't%0A%20%20%20%20solve%2C%20it%20escalates%20to%20their%20manager.%20The%20manager%20can%20handle%20it%20(return%20%60True%60)%0A%20%20%20%20or%20escalate%20further%20(return%20%60False%60).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Aasync%20def%20_(Actor%2C%20MeshFailure%2C%20endpoint%2C%20this_host)%3A%0A%20%20%20%20import%20asyncio%0A%0A%20%20%20%20class%20ActorCrash(BaseException)%3A%0A%20%20%20%20%20%20%20%20pass%0A%0A%20%20%20%20class%20FragileWorker(Actor)%3A%0A%20%20%20%20%20%20%20%20%22%22%22A%20worker%20that%20crashes%20when%20asked.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%40endpoint%0A%20%20%20%20%20%20%20%20async%20def%20do_work(self)%20-%3E%20str%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20ActorCrash(%22GPU%20memory%20error%20on%20this%20worker!%22)%0A%0A%20%20%20%20class%20Supervisor(Actor)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Spawns%20and%20supervises%20children.%20Catches%20their%20failures%20automatically.%22%22%22%0A%0A%20%20%20%20%20%20%20%20def%20__init__(self%2C%20child_procs)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Supervisor%20owns%20these%20children%20because%20it%20calls%20spawn()%0A%20%20%20%20%20%20%20%20%20%20%20%20self.workers%20%3D%20child_procs.spawn(%22fragile%22%2C%20FragileWorker)%0A%20%20%20%20%20%20%20%20%20%20%20%20self.failure_log%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20self._supervised%20%3D%20asyncio.Event()%0A%0A%20%20%20%20%20%20%20%20def%20__supervise__(self%2C%20failure%3A%20MeshFailure)%20-%3E%20bool%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Called%20automatically%20when%20an%20owned%20child%20actor%20fails.%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20self.failure_log.append(str(failure))%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%5BSupervisor%5D%20Caught%20failure%3A%20%7Bfailure%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20self._supervised.set()%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20True%20%20%23%20Handled%20%E2%80%94%20don't%20propagate%20further%0A%0A%20%20%20%20%20%20%20%20%40endpoint%0A%20%20%20%20%20%20%20%20async%20def%20crash_a_child(self)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Tell%20the%20child%20to%20crash%2C%20then%20wait%20for%20supervision%20to%20fire.%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20self.workers.do_work.broadcast()%20%20%23%20fire-and-forget%20%E2%80%94%20triggers%20supervision%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20asyncio.wait_for(self._supervised.wait()%2C%20timeout%3D30)%0A%0A%20%20%20%20%20%20%20%20%40endpoint%0A%20%20%20%20%20%20%20%20async%20def%20get_failure_log(self)%20-%3E%20list%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Return%20failures%20caught%20by%20__supervise__%20(as%20strings).%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20list(self.failure_log)%0A%0A%20%20%20%20%23%20Create%20two%20separate%20proc%20meshes%20(supervisor%20and%20children%20MUST%20be%20on%20different%20meshes)%0A%20%20%20%20supervisor_procs%20%3D%20this_host().spawn_procs(per_host%3D%7B%22gpus%22%3A%201%7D)%0A%20%20%20%20child_procs%20%3D%20this_host().spawn_procs(per_host%3D%7B%22gpus%22%3A%201%7D)%0A%0A%20%20%20%20%23%20Spawn%20supervisor%2C%20passing%20child%20procs%20for%20it%20to%20own%0A%20%20%20%20supervisor%20%3D%20supervisor_procs.spawn(%22supervisor%22%2C%20Supervisor%2C%20child_procs)%0A%0A%20%20%20%20%23%20Tell%20supervisor%20to%20trigger%20the%20child%20%E2%80%94%20broadcast()%20means%20the%20error%20has%0A%20%20%20%20%23%20no%20caller%20to%20return%20to%2C%20so%20the%20actor%20crashes%20and%20supervision%20fires%0A%20%20%20%20await%20supervisor.crash_a_child.call_one()%0A%0A%20%20%20%20%23%20Query%20the%20supervisor's%20failure%20log%0A%20%20%20%20failures%20%3D%20await%20supervisor.get_failure_log.call_one()%0A%20%20%20%20print(f%22%5Cn%3D%3D%3D%20Supervisor's%20failure%20log%20(%7Blen(failures)%7D%20entries)%20%3D%3D%3D%22)%0A%20%20%20%20for%20j%2C%20f%20in%20enumerate(failures)%3A%0A%20%20%20%20%20%20%20%20print(f%22%20%20%5B%7Bj%7D%5D%20%7Bf%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20What%20Just%20Happened%0A%0A%20%20%20%20The%20supervisor%20**owns**%20the%20%60FragileWorker%60%20because%20it%20called%20%60spawn()%60.%20When%0A%20%20%20%20the%20child%20raised%20%60ActorCrash%60%20(a%20%60BaseException%60)%2C%20the%20actor%20died%20and%20Monarch%0A%20%20%20%20delivered%20a%20%60MeshFailure%60%20to%20the%20supervisor's%20%60__supervise__%60%20method.%0A%0A%0A%20%20%20%20Key%20points%3A%0A%0A%20%20%20%20-%20%60__supervise__%60%20receives%20a%20%60MeshFailure%60%0A%20%20%20%20-%20Return%20%60True%60%20-%3E%20%22I%20handled%20it%22%20(stops%20propagation%20up%20the%20tree)%0A%20%20%20%20-%20Return%20%60False%60%20-%3E%20escalate%20to%20the%20supervisor's%20supervisor%0A%20%20%20%20-%20If%20no%20one%20handles%20it%2C%20the%20failure%20reaches%20the%20client%20as%20an%20unhandled%20fault%0A%0A%20%20%20%20This%20allows%20actors%20to%20define%20policies%20of%20what%20to%20do%20if%20Actors%20they%20own%20fail.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20From%20One%20Supervisor%20to%20a%20Tree%0A%0A%20%20%20%20You%20just%20saw%20a%20single%20supervisor%20catch%20one%20child's%20failure.%20Now%20imagine%20this%0A%20%20%20%20at%20scale%20%E2%80%94%20supervision%20forms%20a%20**tree**%20where%20failures%20propagate%20upward%3A%0A%0A%20%20%20%20%60%60%60%0A%20%20%20%20Your%20Script%20(root)%0A%20%20%20%20%E2%94%94%E2%94%80%E2%94%80%20Orchestrator%0A%20%20%20%20%20%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20TrainerSupervisor%0A%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20Trainer%20Rank%200%20%20%E2%9C%93%0A%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20Trainer%20Rank%201%20%20%E2%9C%93%0A%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%E2%94%94%E2%94%80%E2%94%80%20Trainer%20Rank%202%20%20%E2%9C%97%20OOM%0A%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%E2%94%80%20GeneratorSupervisor%0A%20%20%20%20%20%20%20%20%20%20%20%20%E2%94%9C%E2%94%80%E2%94%80%20Generator%200%20%20%20%20%20%E2%9C%93%0A%20%20%20%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%E2%94%80%20Generator%201%20%20%20%20%20%E2%9C%93%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20When%20Trainer%20Rank%202%20crashes%2C%20%60TrainerSupervisor.__supervise__%60%20fires%20first.%0A%20%20%20%20If%20it%20returns%20%60True%60%2C%20the%20failure%20is%20handled%20locally%20%E2%80%94%20the%20Orchestrator%20never%0A%20%20%20%20even%20knows.%20If%20it%20returns%20%60False%60%2C%20the%20TrainerSupervisor%20itself%20fails%2C%20and%20the%0A%20%20%20%20event%20propagates%20up%20to%20the%20Orchestrator.%0A%0A%20%20%20%20This%20is%20just%20like%20exception%20handling%20in%20a%20call%20stack%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20try%3A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20Orchestrator.__supervise__%0A%20%20%20%20%20%20%20%20try%3A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20TrainerSupervisor.__supervise__%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20OOMError()%20%20%20%20%20%20%23%20Trainer%20Rank%202%20crashes%0A%20%20%20%20%20%20%20%20except%20OOMError%3A%20%20%20%20%20%20%20%20%20%20%23%20%20%20-%3E%20handle%20or%20re-raise%0A%20%20%20%20%20%20%20%20%20%20%20%20handle_or_reraise()%0A%20%20%20%20except%20Exception%3A%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%20%20-%3E%20Orchestrator%20handles%20or%20crashes%0A%20%20%20%20%20%20%20%20handle_or_crash()%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20The%20payoff%3A%20instead%20of%20grepping%20through%2016%2C000%20log%20files%2C%20you%20get%20**one%0A%20%20%20%20structured%20chain**%20showing%20exactly%20what%20failed%20and%20how%20the%20failure%20propagated.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20TorchFT%3A%20Fault-Tolerant%20Training%20at%20Scale%0A%0A%20%20%20%20Recall%20the%20419%20interruptions%20from%20Notebook%201%20%E2%80%94%20at%20that%20scale%2C%20restarting%0A%20%20%20%20the%20entire%20job%20each%20time%20is%20unacceptable.%20You%20need%20training%20to%20**continue%0A%20%20%20%20with%20healthy%20replicas**%20while%20failed%20ones%20recover.%0A%0A%20%20%20%20The%20result%3A%20**60%25%20faster%20recovery**%20than%20full%20SLURM%20restarts%2C%20with%20process%0A%20%20%20%20failures%20recovering%20in%20**~90%20seconds**.%20Here's%20how.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20How%20TorchFT%20Works%0A%0A%20%20%20%20TorchFT%20provides%20quorum-based%20training%20%E2%80%94%20instead%20of%20stopping%20the%20whole%20job%0A%20%20%20%20when%20a%20replica%20fails%2C%20the%20remaining%20replicas%20continue%3A%0A%0A%20%20%20%20%60%60%60%0A%20%20%20%20Traditional%20Training%3A%0A%20%20%20%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%0A%20%20%20%20%E2%94%82Replica%200%E2%94%82%20%E2%94%82Replica%201%E2%94%82%20%E2%94%82Replica%202%E2%94%82%20%E2%94%82Replica%203%E2%94%82%0A%20%20%20%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%0A%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%20%20%E2%94%82%0A%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%B4%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%B4%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%E2%96%BC%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20All-reduce%20every%20step%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Single%20failure%20%E2%86%92%20restart%20everything%0A%0A%20%20%20%20TorchFT%20Quorum-Based%20Training%3A%0A%20%20%20%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%20%E2%94%8C%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%90%0A%20%20%20%20%E2%94%82Replica%200%E2%94%82%20%E2%94%82Replica%201%E2%94%82%20%E2%94%82Replica%202%E2%94%82%20%E2%94%82Replica%203%E2%94%82%0A%20%20%20%20%E2%94%82%20healthy%20%E2%94%82%20%E2%94%82%20%20FAILED%20%E2%94%82%20%E2%94%82%20healthy%20%E2%94%82%20%E2%94%82%20healthy%20%E2%94%82%0A%20%20%20%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%0A%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%E2%94%82%20%20%20%20%20%20%20%20%20%20%20%E2%94%82%0A%20%20%20%20%20%20%20%20%20%E2%94%94%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%AC%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%B4%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%80%E2%94%98%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%E2%96%BC%0A%20%20%20%20%20%20%20%20%20%20%20%20Quorum%20shrinks%20to%203%20replicas%0A%20%20%20%20%20%20%20%20%20%20%20%20Training%20continues%20without%20stopping%0A%20%20%20%20%20%20%20%20%20%20%20%20Failed%20replica%20recovers%20and%20rejoins%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20On%20failure%2C%20TorchFT%20catches%20collective%20errors%20through%20its%20own%0A%20%20%20%20ManagedProcessGroup%2C%20isolates%20the%20failure%20to%20a%20single%20replica%20group%2C%20and%0A%20%20%20%20continues%20training%20without%20restarting%20the%20entire%20job.%0A%0A%20%20%20%20A%20Lighthouse%20service%20(Rust%20gRPC)%20coordinates%20quorum%20membership%20via%0A%20%20%20%20heartbeats%20(~100ms)%2C%20while%20a%20Manager%20handles%20checkpoint%20recovery%20when%0A%20%20%20%20replicas%20join%20or%20leave.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Monarch%20%2B%20TorchFT%3A%20Separation%20of%20Concerns%0A%0A%20%20%20%20TorchFT%20handles%20**step-level%20fault%20tolerance**%20%E2%80%94%20catching%20errors%20mid-training%0A%20%20%20%20and%20shrinking%20the%20quorum.%20Monarch%20handles%20**orchestration-level%20recovery**%20%E2%80%94%0A%20%20%20%20respawning%20crashed%20replicas%2C%20managing%20job%20allocation%2C%20and%20escalating%20from%0A%20%20%20%20fast%20process%20restarts%20to%20full%20reallocation%20when%20needed.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Case%20Study%3A%20Qwen3-32B%20Training%20with%20Fault%20Injection%0A%0A%20%20%20%20We%20ran%20this%20on%20a%20**30%20node%20(240%20H100s)%20Coreweave%20cluster**%2C%20training%0A%20%20%20%20Qwen3-32B%20using%20torchtitan%20and%20TorchFT.%0A%0A%20%20%20%20**Test%20conditions%3A**%0A%0A%20%20%20%20-%20Failures%20injected%20at%20~3-minute%20intervals%2C%20100%20total%20events%0A%20%20%20%20-%20Multiple%20failure%20modes%3A%20segfaults%2C%20process%20kills%2C%20NCCL%20abort%2C%20host%0A%20%20%20%20%20%20eviction%2C%20GIL%20deadlock%0A%0A%20%20%20%20**Results%3A**%0A%0A%20%20%20%20%7C%20Metric%20%7C%20Result%20%7C%0A%20%20%20%20%7C--------%7C--------%7C%0A%20%20%20%20%7C%20Recovery%20speed%20vs%20full%20SLURM%20restart%20%7C%20**60%25%20faster**%20%7C%0A%20%20%20%20%7C%20Avg%20recovery%20time%20(process%20failures)%20%7C%20**90%20seconds**%20%7C%0A%20%20%20%20%7C%20Avg%20recovery%20time%20(machine%20failures)%20%7C%20**2.5%20minutes**%20%7C%0A%0A%20%20%20%20**Why%20the%20improvement%3F**%0A%20%20%20%20Monarch%20allows%20for%20configurable%20recovery%20strategies%20based%20on%20failure%20type%20%E2%80%94%0A%20%20%20%20we%20avoid%20unnecessary%20job%20rescheduling%20by%20attempting%20fast%20process-level%0A%20%20%20%20restarts%20first.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20For%20more%20details%20on%20error%20handling%20in%20Monarch%2C%20see%20the%0A%20%20%20%20%5BError%20Handling%20in%20Meshes%5D(https%3A%2F%2Fmeta-pytorch.org%2Fmonarch%2Factors.html%23error-handling-in-meshes)%0A%20%20%20%20documentation.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20**Key%20takeaways%3A**%0A%0A%20%20%20%201.%20**Try%2Fexcept%20first**%3A%20The%20canonical%20pattern%20covers%2090%25%20of%20cases%0A%20%20%20%202.%20**Supervision%20trees**%3A%20Centralized%20error%20surfacing%20%E2%80%94%20one%20place%20to%20see%0A%20%20%20%20%20%20%20what%20went%20wrong%0A%20%20%20%203.%20**Quorum-based%20training**%3A%20Continue%20with%20healthy%20replicas%20while%20failed%0A%20%20%20%20%20%20%20ones%20recover%0A%20%20%20%204.%20**Monarch%20%2B%20TorchFT**%3A%20Orchestration-level%20recovery%20%2B%20step-level%20fault%0A%20%20%20%20%20%20%20tolerance%0A%0A%20%20%20%20These%20three%20patterns%20compose%20%E2%80%94%20try%2Fexcept%20is%20your%20first%20line%20of%20defense%2C%0A%20%20%20%20supervision%20gives%20you%20visibility%2C%20and%20TorchFT%20handles%20training-specific%0A%20%20%20%20recovery%20at%20scale.%0A%0A%20%20%20%20We've%20built%20patterns%20to%20handle%20failures.%20Next%3A%20putting%20it%20all%20together%20%E2%80%94%0A%20%20%20%20services%2C%20weight%20sync%2C%20and%20async%20RL%20loops.%0A%0A%20%20%20%20---%0A%0A%20%20%20%20**Previous%3A**%20%5BNB02%20%E2%80%94%20Interactive%20DevX%5D(.%2F02_interactive_devx.html)%20%C2%B7%20**Next%3A**%20%5BNB04%20%E2%80%94%20Distributed%20Tensors%5D(.%2F04_distributed_tensors.html)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
fb6666bc1f11b79914350b483ff1a824