Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
06b7c6a
[Test] Pin behaviour for @qd.data_oriented with raw qd.ndarray members
hughperkins May 16, 2026
d4350ef
[Fix] Recurse through nested data_oriented / dataclass children when …
hughperkins May 16, 2026
97afa6d
[Fix] Launch-context stale guard fires for @qd.data_oriented containe…
hughperkins May 16, 2026
49a723b
[Test] Extend @qd.data_oriented + ndarray coverage: cross-container n…
hughperkins May 16, 2026
9bdeca5
[Doc] @qd.data_oriented can contain ndarrays
hughperkins May 16, 2026
dc7997b
[Fix] Gap A: template-mapper spec key descends into data_oriented nda…
hughperkins May 16, 2026
906ce19
[Test] Gap A: spec-key descent into data_oriented ndarray members
hughperkins May 16, 2026
a0db648
[Fix] Template-mapper args_hash invalidates when data_oriented ndarra…
hughperkins May 16, 2026
c9598ad
[Fix] Clear error for @qd.data_oriented field type inside typed-datac…
hughperkins May 16, 2026
93893e5
[Perf] Per-class cache of data_oriented ndarray attribute paths for G…
hughperkins May 16, 2026
ce769a7
[Doc] Nesting compatibility matrix for compound types + spot tests
hughperkins May 16, 2026
dd4de40
[Doc] Fix @qd.struct ghost reference in compound_types
hughperkins May 16, 2026
46825ab
[Test] Pin fastcache + @qd.data_oriented + ndarray end-to-end behavior
hughperkins May 16, 2026
ee5fbbb
[Doc] Fastcache with @qd.data_oriented: worked example, semantics, fo…
hughperkins May 16, 2026
b132b81
[Doc] Restructure fastcache.md: simple main body, Advanced subsection…
hughperkins May 16, 2026
6d1c820
[Doc] Use 'member' consistently for compound-type members; drop ambig…
hughperkins May 16, 2026
1de65b9
[Doc] Mirror qd.Template wording for @qd.data_oriented primitive memb…
hughperkins May 16, 2026
a648c3f
[Doc] @qd.data_oriented row: 'types and values' to mirror qd.Template…
hughperkins May 16, 2026
a55d360
[Doc] Tighten path-cache stability restriction: actual failure modes …
hughperkins May 16, 2026
6667ba6
[Test] Fix fastcache cross-init tests: filter captured launches by ke…
hughperkins May 16, 2026
e9c50b4
[Style] pre-commit auto-fixes: black wrap + ruff import-sort
hughperkins May 16, 2026
abf242b
[Doc] Move @qd.kernel inside @qd.data_oriented class in the ndarray-m…
hughperkins May 17, 2026
4c27e2e
[Doc] Document primitive members on @qd.data_oriented self as templat…
hughperkins May 17, 2026
1f539e6
[Doc] State ndarray-member subscript behaviour directly instead of cr…
hughperkins May 17, 2026
730cbcb
[Doc] Drop 'as with dataclasses.dataclass' cross-reference in ndarray…
hughperkins May 17, 2026
57e1b95
[Doc] Simplify fastcache cross-link in @qd.data_oriented section: dro…
hughperkins May 17, 2026
d4ca211
[Doc] Drop ndarray-reassign note and tighten fastcache cross-link in …
hughperkins May 17, 2026
b72a7a7
[Doc] Drop ndarray subscript-access description in @qd.data_oriented …
hughperkins May 17, 2026
18ff7bd
[Doc] Promote fastcache cross-link to its own ### Fastcache subsectio…
hughperkins May 17, 2026
33f4744
[Doc] Rename '### ndarray members' to '### Tensor members'; cover qd.…
hughperkins May 17, 2026
883243e
[Doc] @qd.data_oriented Fastcache subsection: spell out 'disabled for…
hughperkins May 17, 2026
3504250
[Doc] Tensor members: shorten qd.tensor description to 'or qd.Tensor'
hughperkins May 17, 2026
cc01339
[Doc] Tensor members: simplify nested-container sentence to 'Nested @…
hughperkins May 17, 2026
df3113e
[Doc] Fastcache subsection: 'methods of @qd.data_oriented classes'
hughperkins May 17, 2026
7f5fd12
[Doc] Tensor members: drop qd.Vector.ndarray / qd.Matrix.ndarray pare…
hughperkins May 17, 2026
e7fafeb
[Doc] Tensor members: drop the mixing-backends + nesting trailer sent…
hughperkins May 17, 2026
f9a35df
[Doc] Restrictions: drop redundant 'A few combinations are still unsu…
hughperkins May 17, 2026
d336dcd
[Doc] @qd.dataclass section opener: cut to the constraint
hughperkins May 17, 2026
4c5f622
[Doc] Remove top-level Recommendation section
hughperkins May 17, 2026
56a4399
[Doc] Expand @qd.dataclass section: what it does, when to use it, con…
hughperkins May 17, 2026
ef5f8a6
[Doc] @qd.dataclass section: drop use-cases / constraints / cross-ref…
hughperkins May 17, 2026
06580f1
[Doc] @qd.dataclass section opener: explain the kernel-side vs python…
hughperkins May 17, 2026
8899357
[Doc] Restore verbatim prose for the @qd.struct vs other-compound-typ…
hughperkins May 17, 2026
8fef507
[Doc] Replace @qd.struct with @qd.dataclass in opener prose (actual A…
hughperkins May 17, 2026
92f5fe1
[Doc] @qd.dataclass: 'element type of fields' not 'tensors'
hughperkins May 17, 2026
9ea8e5b
[Doc] @qd.dataclass: add sentences about @qd.func methods and qd.type…
hughperkins May 17, 2026
6ff0848
[Doc] @qd.dataclass methods sentence: 'Methods can be added to ... an…
hughperkins May 17, 2026
fd8cd0a
[Doc] @qd.dataclass section: move qd.types.struct paragraph to end wi…
hughperkins May 17, 2026
004cd9a
[Doc] qd.types.struct sentence: drop 'useful when members are compute…
hughperkins May 17, 2026
bf85e4e
[Doc] @qd.dataclass: split into bare-struct example, then methods + @…
hughperkins May 17, 2026
ccaae54
[Doc] First @qd.dataclass example uses AOS layout (the unique-to-Stru…
hughperkins May 17, 2026
820c01a
[Doc] Move 'Nesting compatibility' section to end of compound_types.md
hughperkins May 17, 2026
06d2e86
[Doc] Overview table: dataclasses.dataclass supports differentiation …
hughperkins May 17, 2026
f7dd090
[Test] AD through dataclasses.dataclass with ndarray, field, and qd.t…
hughperkins May 17, 2026
8c0377c
[Doc] compound_types: rephrase intro bullets to describe each type's …
hughperkins May 17, 2026
71a53da
[Doc] compound_types: prefix dataclasses.dataclass with @ in intro/ta…
hughperkins May 17, 2026
46fef24
[Test] AD dataclass: tensor(FIELD) member works when annotated as qd.…
hughperkins May 17, 2026
18f995b
[Doc] tensor: note qd.Tensor is also the dataclass-member annotation
hughperkins May 17, 2026
3ce0ab0
[Doc] compound_types: add 'Under the hood' subsection for each type
hughperkins May 17, 2026
35be370
[Doc] compound_types: rewrite 'Under the hood' subsections at a highe…
hughperkins May 17, 2026
94e455a
[Doc] compound_types: drop 'once' from compile-time capture phrasing
hughperkins May 17, 2026
31b27d7
[Doc] compound_types: replace overview table with differentiating one
hughperkins May 17, 2026
36dc933
[Doc] compound_types: drop 'historical reasons' line
hughperkins May 17, 2026
07dc486
[Fix] _build_struct_nd_paths: handle NamedTuple via _asdict() fallback
hughperkins May 18, 2026
c7d6737
[wip] preserved baseline: stable_members mitigations + new failing test
May 17, 2026
93f597e
[fix] Option A: expand dataclass-instance args in @qd.func calls from…
May 17, 2026
c25f49c
[test] nested dataclasses + chained @qd.func calls from data_oriented…
May 17, 2026
8f64016
[Perf] Prune unused @qd.data_oriented ndarrays via existing pruning m…
hughperkins May 17, 2026
aa9a88f
[Fix] Fastcache hasher: skip QuadrantsCallable/BoundQuadrantsCallable…
hughperkins May 17, 2026
fd8c440
[Perf] Don't over-mark ndarrays during @qd.func dataclass-arg expansion
hughperkins May 17, 2026
e3a3d88
[Perf] TemplateMapper.lookup: only walk template-slot args, cache per…
hughperkins May 18, 2026
067a471
[Fix] Walker robustness: cycle-safe + Pydantic-metaclass-safe is_data…
hughperkins May 18, 2026
cc1e380
[Style] Apply pre-commit (black + ruff): import order, single-line co…
hughperkins May 18, 2026
34f8532
[Fix] stable_members: tolerate opaque members in fastcache hasher + c…
hughperkins May 18, 2026
5e54902
[Fix] stable_members fastcache: only tolerate truly-opaque members, f…
hughperkins May 18, 2026
55ecf95
[Fix] Metaclass-safe is_dataclass for walker over user objects
hughperkins May 18, 2026
6d9c307
[Style] pre-commit: import formatting
hughperkins May 18, 2026
49ffb3b
[Fix] Fastcache: skip opaque-typed members silently by default
hughperkins May 18, 2026
7757907
[Doc] Fastcache: opaque-member silencing is the default; clarify stab…
hughperkins May 18, 2026
fb38fec
Revert "[Doc] Fastcache: opaque-member silencing is the default; clar…
hughperkins May 18, 2026
7cabaa0
Revert "[Fix] Fastcache: skip opaque-typed members silently by default"
hughperkins May 18, 2026
b5b360a
[Fix] Fastcache: replace PARAM_INVALID / silent-skip with qualname fa…
hughperkins May 18, 2026
3aa4fe1
[Fix] test_ad_dataclass: require data64 extension for f64 tests
hughperkins May 18, 2026
dce1305
[Refactor] Fastcache: two-level cache + pruning-driven narrow args walk
hughperkins May 18, 2026
984ac40
[Doc] Fastcache: pruning-driven semantics; stable_members is launch-p…
hughperkins May 18, 2026
12fb215
[Fix] Fastcache: full pruning coverage for data_oriented; remove qual…
hughperkins May 18, 2026
356394e
[Test] Pin pruning-driven fastcache behaviour for @qd.data_oriented args
hughperkins May 18, 2026
45129bc
[Doc] data_oriented(stable_members=...) docstring: correct the failur…
hughperkins May 18, 2026
1f25d9c
[Fix] record_after_call: propagate chain paths through Attribute args
hughperkins May 18, 2026
5fc9b4c
[Fix] Track @qd.func params in fn_param_names for chain-path seeding
hughperkins May 18, 2026
89bb005
[Style] test docstrings: reflow at 120c per repo line-width
hughperkins May 18, 2026
710ee47
[Fix] Fastcache: prune _predeclare_struct_ndarrays by flat-name on ca…
hughperkins May 18, 2026
090f1a8
[CI] Fix linters, pyright, MockContext test, deleted-comment, line-wrap
hughperkins May 18, 2026
be4b030
[Refactor] Move fold_*_into_pruning from Kernel to Pruning
hughperkins May 19, 2026
75c08f6
[Style] Reflow 3 docstring paragraphs to 120c (Check line wrapping)
hughperkins May 19, 2026
29dd841
[Style] Reflow 3 more comment/docstring lines to 120c
hughperkins May 19, 2026
4bd2d10
[Style] Reflow 3 more comment lines to 120c
hughperkins May 19, 2026
aef1a26
[Style] Manually reflow underwrapped prose to 120c
hughperkins May 19, 2026
197d150
[Style] Reflow more underwrapped prose to 120c (round 2)
hughperkins May 19, 2026
173b051
Merge remote-tracking branch 'origin/hp/data-oriented-ndarray-fix' in…
hughperkins May 19, 2026
a47a5ab
[Doc] fastcache.md: restore prose phrasing in unsupported-type + arg-…
hughperkins May 19, 2026
5debfe4
[Doc] fastcache.md: drop redundant 'every child is subject to pruning…
hughperkins May 19, 2026
4e714c7
[Doc] fastcache.md: revert @qd.data_oriented child-rule bullets to or…
hughperkins May 19, 2026
39602c6
[Doc] fastcache.md: tighten recognised-but-unsupported sentence
hughperkins May 19, 2026
bd37c94
[Doc] fastcache.md: restore nested-dataclass + qd.field bullets in da…
hughperkins May 19, 2026
59ce5ff
[Style] args_hasher: restore original 'field offset' comments on Scal…
hughperkins May 19, 2026
a63b834
[Docs] src_hasher: remove pre-refactor background paragraph from modu…
hughperkins May 19, 2026
f6c68d8
[Docs] src_hasher: correct safety-implication paragraph
hughperkins May 19, 2026
ae36b11
[Fix] Per-instance ndarray-path cache for @qd.data_oriented args
hughperkins May 19, 2026
c61d32c
[Test] Strengthen polymorphism + add cache-hit predeclare ndarray test
hughperkins May 19, 2026
706f9b5
[Test] Add bug reproducer: needs_grad not folded into fastcache args_…
hughperkins May 19, 2026
4398af7
[Fix] Fold needs_grad into fastcache narrow args_hash for ndarray leaves
hughperkins May 19, 2026
8a7ead4
[Lint] Reorder imports in needs_grad reproducer test
hughperkins May 19, 2026
8861dc0
Merge remote-tracking branch 'origin/main' into hp/data-oriented-qd-f…
hughperkins Jun 3, 2026
e8bcd18
[Doc] Fix tile16 -> tile link rename; reflow under-wrapped CI flags
hughperkins Jun 3, 2026
44a535f
Merge origin/main into hp/data-oriented-qd-func-dataclass (post-#723)
hughperkins Jun 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions docs/source/user_guide/fastcache.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,17 @@ Fastcache supports the following parameter types:
| `qd.types.NDArray` (scalar, vector, matrix) | Yes | dtype, ndim, layout |
| `torch.Tensor` | Yes | dtype, ndim |
| `numpy.ndarray` | Yes | dtype, ndim |
| `dataclasses.dataclass` | Yes | member types recursively; member values if annotated with `FIELD_METADATA_CACHE_VALUE` (see [Appendix — compound-type cache keying](#compound-type-cache-keying)) |
| `@qd.data_oriented` objects | Yes | member types recursively; primitive member types and values baked into kernel (see [Appendix — compound-type cache keying](#compound-type-cache-keying)) |
| `dataclasses.dataclass` | Yes | member types recursively; member values if annotated with `FIELD_METADATA_CACHE_VALUE` (see [Advanced — compound-type cache keying](#compound-type-cache-keying)) |
| `@qd.data_oriented` objects | Yes | member types recursively, narrowed by pruning (see [Pruning-driven argument hashing](#pruning-driven-argument-hashing)); primitive member types and values baked into kernel (see [Advanced — compound-type cache keying](#compound-type-cache-keying)) |
| `qd.Template` primitives (int, float, bool) | Yes | type and value (baked into kernel) |
| Non-template primitives (int, float, bool) | Yes | type only |
| `enum.Enum` | Yes | name and value |
| `qd.field` / `ScalarField` / `MatrixField` | **No** | — |
| `qd.field` / `ScalarField` / `MatrixField` at a kernel-read path | **No** | — |
| Anything else at a kernel-read path | **No** | — |

If any parameter is of an unsupported type, fastcache is disabled for that call and the kernel falls back to normal compilation. For `qd.field` / `ScalarField` / `MatrixField` arriving through a `qd.Tensor`-annotated parameter, this is silent — no warning is emitted. For other unsupported types, a warning is logged at the `warn` level identifying the offending parameter.
If any kernel-used parameter is of an unsupported type, fastcache is disabled for that call and the kernel falls back to normal compilation. For `qd.field` / `ScalarField` / `MatrixField` arriving through a `qd.Tensor`-annotated parameter, this is silent — no warning is emitted. For other unsupported types, a warning is logged at the `warn` level identifying the offending parameter.

Kernel-unused members of any type — including unrecognised ones — do **not** disable fastcache. The pruning narrowing in the args hasher skips them entirely, so opaque metadata (UUIDs, Pydantic configs, parent back-pointers) attached to a `@qd.data_oriented` instance is harmless as long as the kernel doesn't read it.

### 3. Source code must be available

Expand All @@ -120,6 +123,34 @@ Each compiled artifact is stored under a key derived from all of the following:

When any of these change, the resulting key is different, so a new compilation occurs and a new entry is stored. Previous entries remain on disk — multiple cached versions coexist. You do not need to manually clear the cache when making code changes — the hash mismatch causes a transparent recompilation.

### Pruning-driven argument hashing

Fastcache uses a **two-level cache**:

- **L1** (source + config only): stores the set of *flat names* the kernel actually reads — e.g. `__qd_state__qd_x` for a kernel that reads `state.x`. This is the kernel's pruning info, computed at compile time by the AST builder.
- **L2** (L1 + narrow argument hash): stores the compiled artifact under a key that only hashes the arg paths in the L1 pruning set.

#### Two rules

The args hasher enforces two strict invariants:

1. **The cache key may only include contributions from kernel-pruned paths.** A path is "pruned" (in the pruning-info sense) if Quadrants's compiler recorded the kernel reading it. Pruning info covers:
- Dataclass-flattened param accesses (`__qd_some_dc__qd_field` Names produced by `FlattenAttributeNameTransformer`, marked via `build_Name`).
- Ndarray accesses on data_oriented / template args (`struct_ndarray_launch_info`, folded into the pruning set by `Kernel._fold_struct_nd_paths_into_pruning`).
- Any other attribute-chain access on a kernel arg (`self.dofs.x`, `cfg.n`, …) recorded by `ASTTransformer.build_Attribute`'s `_qd_arg_chain` tracking and folded by `Kernel._fold_kernel_arg_chain_paths_into_pruning`. This covers primitive members baked into the kernel, nested struct paths, and accesses through `@qd.func` callees (propagated by `Pruning.record_after_call`).

Paths *not* in the pruning set are skipped by the args hasher — they are guaranteed not to affect kernel codegen because the kernel cannot read them.

2. **Unrecognised types at kernel-read paths must not be silently dropped or hashed by type-name.** If pruning says the kernel reads a path and the value at that path is a type the args hasher doesn't explicitly handle (Pydantic models, UUIDs, third-party tensor wrappers, …), fastcache is disabled for the call with a one-shot `[FASTCACHE][UNKNOWN_TYPE]` warning identifying the offending type plus an `[INVALID_FUNC]` log line confirming the cache is off. Capturing type identity without type parameters (dtype/shape on a hypothetical tensor type) would silently mask a value-affecting change.

#### Practical implications

- **Kernel-unused members do not affect the cache key.** If a `@qd.data_oriented` container has an opaque metadata member (UUID, Pydantic config, parent-solver back-pointer), and the kernel never reads it, the member is *not* hashed. Changes to `self._uid` or `self.cfg` don't disturb the cache key of a kernel that reads `self.dofs_state.x`.
- **Kernel-unused members of unrecognised types are also fine.** Pruning narrowing skips them before the type-recognition check runs.
- **Kernel-read members of unrecognised types fail fastcache loudly.** Either add explicit handling in `quadrants/lang/_fast_caching/args_hasher.py::stringify_obj_type` (for new tensor-like types whose dtype/shape matter), or move the access out of the kernel-read path (for opaque metadata that shouldn't be there in the first place).

`qd.field` / `ScalarField` / `MatrixField` are *recognised-but-unsupported*: encountering one at a kernel-read path disables fastcache for the call (with a warn-level diagnostic).

## Advanced

### Diagnostics
Expand All @@ -143,13 +174,11 @@ print(obs.cache_stored) # True if the compiled kernel was stored to cach

On the first run you'll see `cache_stored=True` but `cache_loaded=False`. On the second run (after `qd.init`), `cache_loaded=True`.

## Appendix

### Compound-type cache keying

The args hasher walks compound-type kernel parameters recursively. For each leaf member it decides what (if anything) contributes to the cache key. The headline rules:

**`@qd.data_oriented`:** the walker descends into `vars(obj)`. For each child:
**`@qd.data_oriented`:** the walker descends into `vars(obj)`, narrowed by pruning info. For each walked child:

- `qd.ndarray` member — `(dtype, ndim, layout)` is included in the cache key. Element values are not.
- Primitive (`int` / `float` / `bool` / `enum.Enum`) member — value is baked into the kernel (same semantics as a `qd.Template` primitive). Two instances of the same class with different primitive member values get different cache entries.
Expand Down
Loading
Loading