API reference — quiver/take.h (K5)¶
Purpose. K5 — gather by index; dictionary decode; selection-fused decode. Roofline class: Latency/MLP-bound (PRD 08 §4). Introduced: v0.1 (scalar backend). Stability: 0.x-fluid until the v1.0 freeze.
All functions inherit the common contract: noexcept, allocation-free, borrowed views only, thread-compatible pure functions; contract violations assert in debug builds and are UB in release; in-contract inputs are memory-safe and sanitizer-clean (PRD 04 §2, 16).
Contract¶
| API | Semantics |
|---|---|
take(values, indices, out) |
arbitrary order + duplicates legal; every index in-bounds (debug-asserted full scan; release UB) |
dict_decode(dict, codes, n, out) |
out[i] = dict[codes[i]] |
dict_decode(dict, codes, n, sel, out) |
fused: packed out[j] = dict[codes[sel[j]]]; unselected code positions are never read (guard-page proven) |
Codes are uint8/16/32. Interpret performance via memory-level parallelism, not IPC — the dict-size sweep crosses cache levels (PRD 08 §4).
Capacity contracts: PRD 06 §6. Aliasing rules: ADR-023.
Scalar reference (the specification)¶
The family's semantics are defined by src/kernels/take/take_scalar_impl.h (Charter T3) — readable, intrinsic-free, and the oracle every backend must match bit-for-bit.
Per-ISA notes¶
- scalar (v0.1): 4×-unrolled independent loads expose MLP (Survey §3.9). The gather-vs-scalar decision is evidence-gated per ISA at M4/M7 (REQ-K5-004; Survey §4.2).
- AVX2 (v0.2): the gather-vs-scalar question is evidence-gated (REQ-K5-004). Both paths are compiled in
take_avx2.cpp; the shipped default is the scalar 4×-unrolled MLP path, held by the Survey §4.2 prior (gather does not beat scalar independent loads on Haswell–Zen 3 for cache-resident batches). No registered x86 hardware was available at v0.2 to measure, so the decision is provisional-by-prior — protocol and reopening criteria in investigations/k5-gather-avx2.md; the M4 gate records the deferral. The gather path additionally requiresidx < 2^31(vpgatherd*sign-extends 32-bit indices — debug-asserted).dict_decodedelegates to the scalar core (bounds-check structure must stay identical, REQ-K5-002/-003). - NEON (v0.3): the REQ-KERNEL-007 evidence gate is N/A on this ISA — NEON has no gather instruction (Survey §4.1), so the only technique is unrolled independent scalar loads, which is exactly the scalar reference's MLP shape; every entry point delegates and is bit-identical by construction (REQ-K5-004 rationale recorded here).
- AVX-512 (M7): lands with its milestone; techniques per PRD 08 §5 and 09.
Ledger¶
Verdict (Apple M2, v0.3, neon vs autovec): parity (geomean 1.00× over 5 published pairs).
| configuration | neon vs autovec | entries |
|---|---|---|
i64_u32 n=65536/dict=256KiB |
1.03× | qle:apple-m2-20260703-4ec273e2904d-b-bm-take-dict-decode-neon-i64-u32-n-65536-dict-256kib-65536-262144 qle:apple-m2-20260703-4ec273e2904d-b-bm-take-dict-decode-autovec-i64-u32-n-65536-dict-256kib-65536-262144 |
i64_u32 n=65536/dict=32KiB |
1.03× | qle:apple-m2-20260703-4ec273e2904d-b-bm-take-dict-decode-neon-i64-u32-n-65536-dict-32kib-65536-32768 qle:apple-m2-20260703-4ec273e2904d-bm-take-dict-decode-autovec-i64-u32-n-65536-dict-32kib-65536-32768 |
i64_u32 n=65536/dict=4KiB |
0.98× | qle:apple-m2-20260703-4ec273e2904d-bm-take-dict-decode-neon-i64-u32-n-65536-dict-4kib-65536-4096 qle:apple-m2-20260703-4ec273e2904d-b-bm-take-dict-decode-autovec-i64-u32-n-65536-dict-4kib-65536-4096 |
i64_u32 n=65536/dict=65536KiB |
1.00× | qle:apple-m2-20260703-4ec273e2904d-b-bm-take-dict-decode-neon-i64-u32-n-65536-dict-65536kib-65536-67108864 qle:apple-m2-20260703-4ec273e2904d-b-bm-take-dict-decode-autovec-i64-u32-n-65536-dict-65536kib-65536-67108864 |
i64_u32 n=65536/dict=8192KiB |
0.97× | qle:apple-m2-20260703-4ec273e2904d-bm-take-dict-decode-neon-i64-u32-n-65536-dict-8192kib-65536-8388608 qle:apple-m2-20260703-4ec273e2904d-b-bm-take-dict-decode-autovec-i64-u32-n-65536-dict-8192kib-65536-8388608 |
Apple M2 is a secondary platform (secondary_platform, no_pmu: no cycle counters — REQ-LEDGER-008); this is the only registered machine at v0.3 (the three-µarch coverage gate is an open deferral, gate M5). Entries flagged noisy sit in the 3–5% CV band (REQ-LEDGER-005). Reproduction: disputes guide.
Validation¶
tests/unit/test_take.cpp · tests/property/prop_take.cpp · tests/differential/diff_isa_take.cpp (backends vs the naive oracle, byte-exact) · invariant + guard-page suites · bench/micro/bench_take.cpp (hypothesis in-source).
Traceability: REQ-K5-, REQ-KERNEL-; ADR-006/-016/-023/-025 (+ ADR-013 for K6); PRD 04 §5, 08 §5.