Skip to content

Combine quaxify with jit and vmap¤

Put jit outermost¤

quaxify costs Python time on every call: it installs a trace, walks the program primitive by primitive, and allocates as it goes. That cost is per-call and roughly independent of array size, so it dominates small operations.

jax.jit on the outside pays it once, at compile time:

import jax
import jax.numpy as jnp
import quax

# Preferred: jit sees the whole quaxified computation.
fast = jax.jit(quax.quaxify(jnp.add))

# Also correct, but the dispatch runs on every call.
slow = quax.quaxify(jax.jit(jnp.add))

Both give the same answer. The first compiles the dispatch away; the second re-enters the Quax trace on every call. Adding two two-element arrays, the first measured about 15× faster on the machine these docs were written on. Treat the shape of that rather than the number: it is fixed overhead, so the gap widens as arrays get smaller and closes as they get larger.

vmap in either order¤

Here the ordering does not matter: quaxify(vmap(f)) and vmap(quaxify(f)) do the same thing. Pick whichever describes what you mean.

grad is the exception — there the ordering changes what type comes back. See the FAQ.