Skip to content

Commit 25cbe45

Browse files
thisiscamclaude
andcommitted
README: trim effective_order Caveats to user-facing essentials
40 lines of taxonomy, per-primitive lists, and implementation trivia collapsed to 3 bullets: (1) slice to [:effective_order], (2) works through jit and jnp transparently, (3) savings come from nonlinear rules. Per-primitive coverage info already lives in the Coverage section. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4733a03 commit 25cbe45

1 file changed

Lines changed: 7 additions & 39 deletions

File tree

‎README.md‎

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -233,45 +233,13 @@ batched = jax.vmap(taylor)(xs, ks)
233233

234234
### Caveats
235235

236-
- `effective_order` propagates across both explicit (`jax.jit`) and
237-
implicit (`jnp.*` operator) jit boundaries. The implementation binds
238-
`effective_order` as an extra runtime input to each inner pjit so the
239-
inner `JetTrace` reads it as a tracer and threads it into every
240-
primitive rule's `_jet_scan` call. No special action needed from the
241-
user — write your function in plain `jnp` style and the hint is
242-
honored throughout.
243-
- The primitives a JAX program uses fall into three categories:
244-
- **Linear / zero-derivative** (`add`, `sub`, multiplication by a
245-
constant, `neg`, broadcasting, slicing, comparisons, …): the operation
246-
applies elementwise along the order axis — `(a + b)[k] = a[k] + b[k]`
247-
— so it is already a single `O(K)` XLA op over the series array.
248-
There is no convolution loop to short-circuit, and `effective_order`
249-
has no effect. Output entries above `effective_order` still hold
250-
correct values for these primitives, because the linear op computes
251-
every entry uniformly.
252-
- **Nonlinear with an `effective_order`-aware rule.** Currently
253-
`exp`, `expm1`, `log`, `log1p`, `pow`, `integer_pow`, `logistic`,
254-
`tanh`, `erf_inv`, `div`, `sin`, `cos`, `sinh`, `cosh`, `mul`,
255-
`dot_general`, `conv_general_dilated`, `erf`, `atan2`, `cumprod`,
256-
`cummax`, `cummin`, and any future `def_deriv`-registered primitive.
257-
The convolution scan short-circuits iterations beyond
258-
`effective_order`. Output entries above `effective_order` are
259-
unspecified — slice to `series_out[:effective_order]` before using
260-
them.
261-
- **Linear-style fan-out rules** (`abs`, `max`, `min`, `gather`,
262-
`select_n`, `scatter-add`, `reduce_max`, `reduce_min`): each rule
263-
applies an op independently to every series index via `vmap`, the
264-
same shape as `add`/`sub` in the linear bucket. They don't
265-
short-circuit, but they don't need to — the per-entry cost is O(1)
266-
and the contract is satisfied because garbage-in-garbage-out for
267-
indices above `effective_order` is fine.
268-
- One-time cost: when `effective_order` is set, each inner pjit re-traces
269-
with one extra input (the eff scalar). This adds a small compile-time
270-
cost the first time a function is `jet`'d with `effective_order` set vs
271-
without — both jaxprs are cached.
272-
- Because output entries above `effective_order` are unspecified for the
273-
second category, treat the whole `series_out[effective_order:]` slice as
274-
garbage even if upstream linear ops would otherwise leave it intact.
236+
- Slice the result to `series_out[:effective_order]`. Entries above the
237+
threshold are unspecified.
238+
- `effective_order` works through `jax.jit` and `jnp.*` automatically.
239+
No need to rewrite your function in `lax.*` style.
240+
- The savings come from short-circuiting the `O(K²)` convolutions in
241+
nonlinear rules. Linear ops (`add`, `broadcast`, `reshape`, …) are
242+
already `O(K)` and unaffected.
275243
- The win is largest when the dominant cost is in the convolution-style
276244
loops that the hint short-circuits. For shallow programs the overhead of
277245
the conditional may exceed the savings.

0 commit comments

Comments
 (0)