@@ -467,7 +467,10 @@ Numba 非常高效地处理了这个顺序运算。
467467``` {code-cell} ipython3
468468cpu = jax.devices("cpu")[0]
469469
470- @partial(jax.jit, static_argnames=("n",), device=cpu)
470+ # Pin the input to the CPU, which keeps the whole computation there
471+ x0_cpu = jax.device_put(0.1, cpu)
472+
473+ @partial(jax.jit, static_argnames=("n",))
471474def qm_jax_fori(x0, n, α=4.0):
472475
473476 x = jnp.empty(n + 1).at[0].set(x0)
@@ -481,7 +484,7 @@ def qm_jax_fori(x0, n, α=4.0):
481484```
482485
483486* 我们将 ` n ` 设为静态,因为它影响数组大小,JAX 希望在编译代码中针对其值进行特化处理。
484- * 我们通过 ` device=cpu ` 将计算固定到 CPU,因为这种顺序工作负载由许多小型运算组成,几乎没有机会利用 GPU 并行性。
487+ * 我们通过 ` jax.device_put ` 将输入固定到 CPU(从而使整个计算保持在 CPU 上) ,因为这种顺序工作负载由许多小型运算组成,几乎没有机会利用 GPU 并行性。
485488
486489重要提示:虽然 ` at[t].set ` 看起来在每一步都创建了一个新数组,但在 JIT 编译的函数内部,编译器会检测到旧数组不再需要,并就地执行更新!
487490
@@ -490,7 +493,7 @@ def qm_jax_fori(x0, n, α=4.0):
490493``` {code-cell} ipython3
491494with qe.Timer():
492495 # First run
493- x_jax = qm_jax_fori(0.1 , n)
496+ x_jax = qm_jax_fori(x0_cpu , n)
494497 # Hold interpreter
495498 x_jax.block_until_ready()
496499```
@@ -500,7 +503,7 @@ with qe.Timer():
500503``` {code-cell} ipython3
501504with qe.Timer():
502505 # Second run
503- x_jax = qm_jax_fori(0.1 , n)
506+ x_jax = qm_jax_fori(x0_cpu , n)
504507 # Hold interpreter
505508 x_jax.block_until_ready()
506509```
@@ -514,7 +517,7 @@ JAX 对于这种顺序运算也相当高效!
514517这种替代方案可以说更符合 JAX 的函数式风格——尽管语法难以记忆。
515518
516519``` {code-cell} ipython3
517- @partial(jax.jit, static_argnames=("n",), device=cpu )
520+ @partial(jax.jit, static_argnames=("n",))
518521def qm_jax_scan(x0, n, α=4.0):
519522 def update(x, t):
520523 x_new = α * x * (1 - x)
@@ -531,7 +534,7 @@ def qm_jax_scan(x0, n, α=4.0):
531534``` {code-cell} ipython3
532535with qe.Timer():
533536 # First run
534- x_jax = qm_jax_scan(0.1 , n)
537+ x_jax = qm_jax_scan(x0_cpu , n)
535538 # Hold interpreter
536539 x_jax.block_until_ready()
537540```
@@ -541,7 +544,7 @@ with qe.Timer():
541544``` {code-cell} ipython3
542545with qe.Timer():
543546 # Second run
544- x_jax = qm_jax_scan(0.1 , n)
547+ x_jax = qm_jax_scan(x0_cpu , n)
545548 # Hold interpreter
546549 x_jax.block_until_ready()
547550```
0 commit comments