Fix eager error_if hanging when inputs are sharded over multiple devices#1242
Fix eager error_if hanging when inputs are sharded over multiple devices#1242discobot wants to merge 1 commit into
error_if hanging when inputs are sharded over multiple devices#1242Conversation
|
Hi there! Thank you for this, and sorry for taking a few weeks to get around to it :) The reason for the delay is that we've been beavering away at landing a number of other improvements to Would you be interested in rebasing this branch on top of I need to stare at the implementation a little bit – I'm not an expert on multi-device JAX – but I don't love the special-casing of this case. Would it be possible to just 'always' move to a single device... which will be a no-op in the inherently-single-device case? |
fe8bce1 to
5fc11c5
Compare
|
Thanks, and no worries about the delay! Rebased onto One judgement call worth your eye: I restore the input sharding onto the output, so error_if stays transparent in the non-raising |
In eager mode `error_if` jits its implementation, so a multi-device-sharded input compiles an SPMD program; when the error fires the exception raised inside `pure_callback` tears down one device while its peers hang at the next collective, aborting the process (patrick-kidger#1232). Move the inputs onto a single device before the eager check (a no-op when they already live on one) and restore each output's original sharding afterwards. error_if, warn_if and branched_error_if all route through `_error_impl`, so this covers all three.
5fc11c5 to
8c71e6b
Compare
Fixes #1232.
The hang happens because eager
error_ifroutes throughfilter_jit, so amulti-device-sharded input compiles an SPMD program over every device in the
sharding. The all-reduce in the abort trace sits inside the
lax.conderrorbranch: once the exception from
jax.pure_callbackkills one device'sexecution thread, its peers never reach the collective and XLA aborts the
process when the rendezvous times out.
This PR handles that case before the jit: if every input is concrete (no
tracers) and fully addressable, and at least one is sharded over more than one
device, then the predicate is evaluated on the host. On error, the inputs are
copied to the host and passed to the existing
branched_error_if_impl_jit,which then compiles a single-device program -- so the usual
EquinoxRuntimeErrorreporting is unchanged. For the non-raisingon_errormodes, each output leaf's original sharding is restored with
jax.device_put.Traced or non-fully-addressable inputs fall through to the current behaviour.
One known limitation:
error_ifunder a user'sjax.jitover multi-deviceinputs still aborts in the same way (verified locally). There the multi-device
program is what the user asked for, and the underlying problem -- a raising
callback inside an SPMD program -- doesn't look fixable from inside
error_if.This PR covers eager mode, as reported.
Tested with the two CPU devices already configured in
tests/conftest.py: thenew test aborts the process (exit 134) without the fix and passes with it,
covering replicated and non-replicated shardings, each of
x/predshardedalone, and sharding preservation on the false-predicate and
on_error="nan"/"off"paths.