mixle.engines.jax_engine module

JAX implementation of the ComputeEngine protocol – XLA arrays, functional autograd, GPU/TPU.

JAX’s jax.numpy mirrors the NumPy API, so most ops alias straight through (no axis->``dim`` translation as Torch needs). Three JAX-isms are handled here:

  • float64 is opt-in, and it is the caller’s global setting, not this module’s. JAX defaults to float32 and treats jax_enable_x64 as a process-wide flag that JAX itself only documents as reliable when set before any JAX computation runs – so this module never calls jax.config.update(...) itself; doing that on import would silently reconfigure unrelated JAX code sharing the process, including code that already initialized JAX before Mixle was imported. Instead the engine reads the ambient jax.config.jax_enable_x64 at construction: when the caller enabled it themselves (e.g. jax.config.update("jax_enable_x64", True) at application start, before touching JAX), the engine’s default dtype and accumulator_dtype are float64 as before; when it is off, both fall back to float32 – the precision JAX would silently truncate a float64 request to anyway – so the engine never claims a precision the runtime cannot deliver. Pass dtype= explicitly to override either way, with one exception: an explicit float64 on an unenabled runtime is refused rather than demoted (MXR-080-1559), since a caller who named the precision is relying on it and must be told the runtime cannot supply it.

  • device placement is explicit and validated. device resolves to a concrete jax.Device at construction time (default "cpu"; also accepts "gpu", "tpu", or "platform:index"). A platform or index that does not exist in the current JAX runtime raises ValueError immediately. Every allocation/conversion method places its result on that resolved device via jax.device_put, so a requested device is never just a label JAX’s own runtime default silently overrides.

  • arrays are immutable. index_add uses the functional arr.at[idx].add(...) update and returns the new array (return-value-only, like the Torch engine).

Autograd is functional in JAX (jax.grad / value_and_grad), not tensor-tagged, so requires_grad() is always False even though supports_autograd is True. Like every non-host engine it keeps resident_estep=True / supports_numba=False: scoring runs on JAX arrays, and the E-step round-trips through host NumPy unless an engine-resident kernel is registered.

jax_array_placement(x)[source]

The placement a concrete JAX array actually has, for engine discovery (MXR-080-1561).

mixle.engines.engine_of builds a JaxEngine from a bare array. Passing no device made every JAX array – wherever it really lived – resolve to the default CPU device, so a GPU or TPU array’s ownership was relabeled as CPU and _engines_compatible’s placement check (which compares str(engine.device)) could not tell two different devices apart. Recover the array’s own placement instead.

Returns whatever JAX reports: a single jax.Device for an ordinary array, or a Sharding for a distributed one (both are accepted by jax.device_put, and both stringify distinguishably). None – meaning “could not determine”, so the caller keeps the previous default – is returned only when the object exposes neither accessor, which keeps discovery working against JAX versions that name them differently rather than making placement a hard dependency.

Parameters:

x (Any)

Return type:

Any

class JaxEngine(device=None, dtype=None, compile=False)[source]

Bases: ComputeEngine

JAX array engine: XLA-compiled ops, float64, optional jax.jit compilation, GPU/TPU via JAX.

Parameters:
  • device (str | None)

  • dtype (Any)

  • compile (bool)

property accumulator_dtype: Any

High-precision dtype for sufficient-statistic reductions (float64, or float32 when the ambient jax_enable_x64 is off – see the module docstring; JAX would silently truncate a float64 accumulator request to float32 there anyway, so this avoids claiming a precision the runtime cannot actually give).

with_precision(precision)[source]

Return a JAX engine with the same placement and a new dtype policy.

Parameters:

precision (Any)

Return type:

JaxEngine

asarray(x, dtype=None)[source]

Convert x to a JAX array on this engine’s device. Float inputs are force-cast to the engine dtype (float64 by default) unless dtype is given – matching the Torch engine’s contract, not NumPy’s.

Complex input is rejected when dtype is not given explicitly (MXR-080-1560), exactly as mixle.engines.torch_engine.TorchEngine.asarray() does: this engine’s dtype policy has no complex-precision concept, so the generic non-floating/non-Boolean fallback (jnp.int64) would silently discard the imaginary component and collapse the real part to an integer. Pass dtype=jnp.complex64/jnp.complex128 for a genuine complex array.

Parameters:
Return type:

Any

zeros(shape, dtype=None)[source]

Allocate a zero array with this engine’s dtype, placed on this engine’s device.

Parameters:
Return type:

Any

empty(shape, dtype=None)[source]

Allocate an array on this engine’s device (JAX has no uninitialized empty; zeros is the safe equivalent).

Parameters:
Return type:

Any

arange(*args, **kwargs)[source]

Return jnp.arange placed on this engine’s device; float arguments select the engine float dtype.

Parameters:
Return type:

Any

is_concrete(x)[source]

False while x is a jit tracer: its values do not exist yet, so to_numpy would raise.

Parameters:

x (Any)

Return type:

bool

to_numpy(x)[source]

Move a JAX array back to a host NumPy array.

Parameters:

x (Any)

Return type:

ndarray

stack(arrays, axis=0)[source]

Stack arrays with jnp.stack, placed on this engine’s device.

Parameters:
Return type:

Any

concatenate(arrays, axis=0)[source]

Join arrays with jnp.concatenate on this engine’s device.

Parameters:
Return type:

Any

requires_grad(x)[source]

Always False: JAX autograd is functional (jax.grad), not tensor-tagged.

Parameters:

x (Any)

Return type:

bool

compile(fn)[source]

Compile fn with jax.jit when enabled.

Parameters:

fn (Callable)

Return type:

Callable

index_add(out, index, values)[source]

Add values into out along axis 0 via the functional .at[idx].add update, placed on this engine’s device.

Contract: return-value-only – JAX arrays are immutable, so this returns a new array; callers must use the return value (the same contract the Torch engine documents).

Parameters:
Return type:

Any