JAX Best Practices
Avoid common pitfalls, debug effectively, write performant JAX code, and follow proven patterns for production-quality JAX applications.
Common Pitfalls and How to Avoid Them
Arrays are immutable
Never try
x[0] = 5. Usex = x.at[0].set(5)instead. This creates a new array (but JAX optimizes it under JIT).JIT tracing vs execution
Python side effects (print, list.append) only run during tracing, not on subsequent JIT calls. Use
jax.debug.print()for debugging inside JIT.Random number handling
Always split PRNG keys explicitly. Never reuse a key:
key, subkey = jax.random.split(key).Control flow inside JIT
Use
jax.lax.condinstead of Python if/else, andjax.lax.fori_loopinstead of Python for loops when the condition depends on array values.
Debugging JAX Code
import jax # Debug prints inside JIT @jax.jit def train_step(params, x, y): loss = loss_fn(params, x, y) jax.debug.print("loss: {}", loss) # Works inside JIT! return loss # Disable JIT for debugging with jax.disable_jit(): result = train_step(params, x, y) # Runs as pure Python # Check for NaN/Inf jax.config.update("jax_debug_nans", True) # Raises error on NaN # Print compilation info jax.config.update("jax_log_compiles", True)
Performance Tips
| Tip | Why It Matters |
|---|---|
| JIT everything | Un-JITted code dispatches each op individually to the GPU - massive overhead |
| Avoid Python loops over data | Use vmap or jax.lax.scan instead of for loops |
| Minimize host-device transfers | Keep data on the device; avoid .numpy() in hot loops |
| Use donate_argnums | jax.jit(fn, donate_argnums=(0,)) lets JAX reuse input buffers |
| Profile with JAX profiler | jax.profiler.trace() generates TensorBoard-compatible profiles |
| Batch operations | Large batched operations are much more efficient than many small ones |
PRNG Key Management
import jax key = jax.random.PRNGKey(0) # WRONG: reusing the same key gives identical results # a = jax.random.normal(key, (3,)) # b = jax.random.normal(key, (3,)) # Same as a! # RIGHT: split the key for each use key, k1, k2 = jax.random.split(key, 3) a = jax.random.normal(k1, (3,)) b = jax.random.normal(k2, (3,)) # Different from a # Pattern for training loops for step in range(num_steps): key, subkey = jax.random.split(key) params, loss = train_step(params, subkey, batch)
When to Use JAX
Course Complete!
You now understand JAX from fundamentals to advanced topics. Continue learning by exploring FastAI for rapid prototyping or Hugging Face Transformers for NLP.
Next Course: FastAI →Ready to Go Deeper?
Live instructor-led courses from our partners. Affiliate disclosure.
AI & ML Courses - 30% Off
Live instructor-led AI, machine learning, data science, and cloud courses for working professionals. Use code Limited30 at checkout.
EdurekaDataCamp - AI & Data Science
Hands-on Python, machine learning, and AI courses with interactive exercises and real projects.
DataCampedX - Top AI Courses
University-level AI courses from MIT, Harvard, Stanford. Earn certificates that employers recognize.
edX