@@ -471,7 +471,10 @@ We'll apply a `lax.fori_loop`, which is a version of a for loop that can be comp
471471```{code-cell} ipython3
472472cpu = jax.devices("cpu")[0]
473473474-@partial(jax.jit, static_argnames=("n",), device=cpu)
474+# Pin the input to the CPU, which keeps the whole computation there
475+x0_cpu = jax.device_put(0.1, cpu)
476+477+@partial(jax.jit, static_argnames=("n",))
475478def qm_jax_fori(x0, n, α=4.0):
476479477480 x = jnp.empty(n + 1).at[0].set(x0)
@@ -485,7 +488,7 @@ def qm_jax_fori(x0, n, α=4.0):
485488```
486489487490* We hold `n` static because it affects array size and hence JAX wants to specialize on its value in the compiled code.
488-* We pin to the CPU via `device=cpu` because this sequential workload consists of many small operations, leaving little opportunity for GPU parallelism.
491+* We pin the input to the CPU with `jax.device_put` (which keeps the whole computation on the CPU) because this sequential workload consists of many small operations, leaving little opportunity for GPU parallelism.
489492490493Important: Although `at[t].set` appears to create a new array at each step, inside a JIT-compiled function the compiler detects that the old array is no longer needed and performs the update in place!
491494@@ -494,7 +497,7 @@ Let's time it with the same parameters:
494497```{code-cell} ipython3
495498with qe.Timer():
496499 # First run
497- x_jax = qm_jax_fori(0.1, n)
500+ x_jax = qm_jax_fori(x0_cpu, n)
498501 # Hold interpreter
499502 x_jax.block_until_ready()
500503```
@@ -504,7 +507,7 @@ Let's run it again to eliminate compilation overhead:
504507```{code-cell} ipython3
505508with qe.Timer():
506509 # Second run
507- x_jax = qm_jax_fori(0.1, n)
510+ x_jax = qm_jax_fori(x0_cpu, n)
508511 # Hold interpreter
509512 x_jax.block_until_ready()
510513```
@@ -521,7 +524,7 @@ although the syntax is difficult to remember.
521524522525523526```{code-cell} ipython3
524-@partial(jax.jit, static_argnames=("n",), device=cpu)
527+@partial(jax.jit, static_argnames=("n",))
525528def qm_jax_scan(x0, n, α=4.0):
526529 def update(x, t):
527530 x_new = α * x * (1 - x)
@@ -538,7 +541,7 @@ Let's time it with the same parameters:
538541```{code-cell} ipython3
539542with qe.Timer():
540543 # First run
541- x_jax = qm_jax_scan(0.1, n)
544+ x_jax = qm_jax_scan(x0_cpu, n)
542545 # Hold interpreter
543546 x_jax.block_until_ready()
544547```
@@ -548,7 +551,7 @@ Let's run it again to eliminate compilation overhead:
548551```{code-cell} ipython3
549552with qe.Timer():
550553 # Second run
551- x_jax = qm_jax_scan(0.1, n)
554+ x_jax = qm_jax_scan(x0_cpu, n)
552555 # Hold interpreter
553556 x_jax.block_until_ready()
554557```