wai: keep loaded parameter sets between decodes, keyed by the SHA-256 of their bytes (O23) #268
Loading…
Reference in a new issue
No description provided.
Delete branch "wai/o23-loaded-set-cache"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Stacked on #267 (
wai/d2c-m4, still open): this branch is based on its head2143d25b, so until #267 merges the diff below also shows #267's commits. The seven commits frome2a93241to4d7b9e28are this PR's own.What
Since the decoders were re-expressed through
wai-ops/1, every integer decode lowers its parameter set and loads each graph, the bounds pass (load step 8) included, on every call. That is the same work for every payload the set decodes, and for the pretrained conditional-codec set it costs more than the decode. This PR keeps a set once it has loaded and reuses it.int_set_cache::LoadedSets(new,neural_int). One store per process, behind a lock (onwasm32, one thread). Entries are found by aSetKey: the capability, the lowering, the profile the graphs were loaded under, and the SHA-256 of the listing of the members the decode reads, each listed by its own SHA-256 (pin::listing_from). That is the digest a pin over exactly those members names. The key is never a name.int_payload::decode_intandint_payload::declared_costforWIH1, aWIV1's keyframe,WIA1,WIS1andwai.neural.int_synth. Through these, the neural sink andwai-web'sdecodeWiv1,decodeWih1,decodeWia1,decodeWis1anddecodeIntSynthuse it too.decodeIntSynthnow decodes throughdecode_intlike the others, so a refusal's message starts with its code.int_synth::decode_from_specis shared with the byte-equality crate, which includes the decoder sources and not the store. It is now three steps (check_payload,load_spec,decode_loaded) and loads its set every time.wai_ops::Loadedis made only bygraph::load.cond_checked,int_audio::ops::plan_with,int_splat::ops::plan_with, andint_synth::check_payload.LoadedSets::DEFAULT_BUDGET). The least recently used entry goes first, a set larger than the whole budget is not kept, and a budget of 0 turns the store off (the set is then not hashed).LoadedSets::set_budget, orsetLoadedSetBudgetinwai-web;loadedSetStatsreports for a page.wai_ops::Graph::heap_bytes(new: every list at capacity × element size), plus 4096 bytes for its share of the two indexes.resolve(or a pinned one with a key log) already hashes every member the decode reads, and their listing, for check 5.IntParamskeeps that listing digest with the member names it was formed over. The key uses it only for a capability that reads exactly those members; any other key hashes the bytes. The bytes are borrowed for as long as the parameters live.include/wai.hgains the two associated constants that cbindgen exports (LoadedSets_DEFAULT_BUDGET,LoadedSets_INDEX_BYTES_PER_ENTRY).Declared cost
working_bytesis what a decode holds beyond the payload and its parameter set. For a capability that decodes through the operator set, the set is already counted (bytests/int_payload_cost.rs) as parsed, lowered and loaded, the same for every payload. A kept entry is that set, kept. So it is the set's memory, outside every decode's declared working bytes, and the store's budget bounds it.tests/int_payload_cost.rsruns its checks in three ways:working + set, as before.It also checks the store's count against a live-bytes allocator. The count is never under what the store holds:
video_nktinyTests
tests/int_set_cache.rs(new; in both conformance steps):tiny,video_nk,audio,splatand the fourint_synthcorpus vectors. The declared cost finds the set held too.tinyg_sbias byte, and anint_synthbias digit.int_synth:overflow_acc64, refused by the bounds pass atLoad(8), beside its neighbour with bias 0;tinywith a layer-0 bias that admits no input range, refused as it is lowered.Elsewhere:
int_set_cache(5).int_payload::tests::a_resolved_digest_keys_only_the_members_it_was_formed_over.wai_ops::graph::tests::heap_bytes_count_every_list.wai-web/demo/verify_int_payload_wasm.mjsdecodestinytwice in wasm32 and counts the hit, then decodes with a budget of 0.Falsifications
Each was applied to the committed final head
4d7b9e28, run red on the build host, and restored withgit checkout. The tree was then byte-equal to that head, which is green (gate below). The same faults were also shown red on earlier heads of this branch.int_set_cacheEXIT=101, 5 of 6 tests. "tiny: kept under the SHA-256 of its members".overflow_acc64is not "refused again, with the same refusal": it decodes with its one-byte neighbour's certified graph. "the set one byte away is decoded with its own networks" (wrong image). The least-recently-used test got[5, 10, 15]for[5, 10, 20]. A refusal fixture's set is not under its keyint_set_cacheEXIT=101 (5 tests). "tiny: the first decode loads its set and keeps it"(0, 1, 0)for(1, 0, 1), a hit on another set's entry.overflow_acc64decodes. The one-byte neighbour gets the wrong image.[255, 0, 0]for[5, 10, 15]. Threads(8, 2)for(8, 1)int_set_cacheEXIT=101: "wiv1_geometry: with its set held",field_range"i_frame size disagrees with h·w·3" forgeometry_mismatch"the keyframe's size is not the clip's h × w"the_least_recently_used_entry_goes_first);int_set_cacheEXIT=101 ("s2 went first")int_payload_costEXIT=101 ("video_nk: the store holds 9693 bytes for the set and counts 8061");wai-opsheap_bytes_count_every_listEXIT=101 (39 for 57)int_set_cacheEXIT=101 (6 of 6)resolveformed is used for any capability's membersMeasured
The pretrained conditional-codec set: 24.3 MB in three members (
f16fd09c…), 256×256, throughdecode_int(WIH1). It was run on the build host in release, in three processes per row, at a 1-minute host load of about 20–43 (stated per run in the report). Every decode gaveeb1acd2159f8a966. The set counts 93,204,616 bytes in the store (93,203,464 on wasm32).resolveonceresolveper callresolve's check-5 hash)resolveonce (two processes)decodeWih1,resolveper call)The SHA-256 of the set's members (software
sha2) takes 59–69 ms (medians). Before the last commit the key formed it on every decode, as well asresolve's. Now a decode through parametersresolvebuilt does not form it again.Gate
gate.sh o23-final2on4d7b9e28: GREEN. Main (ca79392a) is already in this branch, so no merge was needed. The steps: build, lib-tests, carriage, corpus loop 21/21, fast-kernels, byte-exact, wai-web wasm32, neural gates.Also EXIT=0 on that head:
WAI_REQUIRE_SOTA_VECTORS=1:int_hyper_synth,int_video_sota_keyframe,require_vectors_rule);neural_native_decodeandneural_cost_limit;wasm-bindgen-test-runner0.2.127;verify_int_payload_wasm(with the new hit and budget-0 checks),verify_int_synth_wasm,verify_int_hyper_wasmon the pretrained set (eb1acd2159f8a966, JSON and binary model) andverify_staged_wasm;check-lockfiles.sh: 38 lockfiles current.Locally, all EXIT=0: comparative prose, vanity metrics, public names, section refs, tests in CI, orphan sources and workflow concurrency.
include/wai.hwas regenerated once (1bd2547b) and is unchanged by every build since.git status --porcelain --untracked-files=nowas empty after each build.An earlier gate on
5c456dc4was RED in byte-exact: that crate#[path]-includesint_synth.rsandint_hyper_synth.rsand has no store.4d7b9e28fixed it.Not in this PR
/int_hyperdemo page decodes once per view (through the debugdecodeIntHyperBin), so a store does not change it. A faster bounds pass is the lever there.🤖 Generated with Claude Code
D2c M4, gate 1 (extensions/integer-operators.md §13.2, §13.0, §13.5). - int_hyper_synth::ops: lower (h_s by whm1/1, then g_s by whm1/1 with the RGB8 step, from the models this crate parses) and load (each loaded under acc64 in turn, as the decode will hold them: Nets). - int_ops::whm1_net refuses a model whose weights are past i16 or whose inverse-GDN gamma is past i32 (model_mismatch): the widths WHM1 gives them and whm1/1 writes them at. A model parsed from WHM1 bytes never has one; a JSON model (the tools' form, which the browser's debug decode and the byte-exact keyframe golden read) could, and its graph would otherwise hold truncated values. Unit test int_ops::conversion at both ends of each width. - tests/int_hyper_ops.rs (video_int, legacy_int; named in both fast-kernels steps): every committed set of wai.neural.int_hyper and wai.video.int_hyper (tiny under both, the synthetic hyper) lowers to its committed h_s.whg1 and g_s.whg1 from its bytes and from the parsed models; its set digest, the certificate's graph digests and input check ranges are those graphs'; each graph loads under acc64 and not acc32; the first acc32 failure is h_s input 0, range, 53 bits for tiny (Appendix C) and 52 for hyper; the tiny set's JSON models lower to the same graphs as its binary ones. The pretrained set's committed certificate (f16fd09c) has Appendix C's verdict (41 bits). - tests/int_hyper_synth.rs: the_pretrained_set_lowers_to_its_certificates_graphs (the regenerated set is f16fd09c, and ops::lower writes the graphs its certificate records); named in wai-sota-vectors.yml's required list, whose path filters gain src/int_ops.rs. Green (build host, logs wai-build/logs/d2c-m4/g1): int_hyper_ops debug and release EXIT=0 (2 passed); --lib int_ops:: EXIT=0 (4); the SOTA step (WAI_REQUIRE_SOTA_VECTORS=1, vectors regenerated on the build host from the pinned stack: set digest f16fd09c, as committed) EXIT=0, 7 passed, the new test included; check-tests-in-ci.py EXIT=0. Falsified: h_s lowered with the RGB8 step in ops::lower. Red: int_hyper_ops EXIT=101 ("tiny: the lowering of the parsed models differs from the committed h_s"); the SOTA test EXIT=101 (h_s's graph digest is not the certificate's). Restored with git; green above is this commit. Co-Authored-By: Claude Opus 5.5 <[email protected]>D2c M4, gate 2 (golden equality). - int_hyper_synth: the stream decodes factored out of the checked decode (hyper_latent, latent; unchanged), the direct decode kept as legacy::decode_conditional_checked (decode_conditional_checked still calls it: the switch is gate 6), and ops::{plan, decode, decode_loaded}: the plan (cond_plan, integer-payloads §7's order), the two networks lowered and loaded, the hyper-latent stream, h_s's graph, the driver's split of its output into sigma (channels [0, m)) and mu ([m, 2m)) after the shape check (§13.5), the latent stream conditioned on sigma, g_s's graph ending in the RGB8 step, then HWC bytes. - tests/int_hyper_ops.rs: every committed vector decodes through the lowering to the direct decode's image and every committed digest: tiny (WIH1, its JSON form, and the set's JSON models: SHA-256 sidecar dce7282d…, FNV-1a 7cbe882c42c6725d) and video_nk (WIV1 keyframe 1: the keyframe, then the P-frames, every frame's and the clip's SHA-256 4a81f0c9… and FNV-1a). - byte-exact-conformance: wih1_through_its_lowering_is_golden (reference and fast kernels), wiv1_keyframe_1_through_its_lowering_is_golden, and the_neural_keyframe_clip_through_its_lowering_is_byte_identical (the JSON models neural_keyframe_golden reads, now with the check ranges; clip FNV-1a a5f53d477999d159). - tests/int_hyper_synth.rs: the pretrained set's binary models also decode through the lowering to the export image (wai-sota-vectors.yml). Green (build host, logs wai-build/logs/d2c-m4/g2, g2v): int_hyper_ops debug and release EXIT=0 (3 passed); cargo check --lib --features neural_int EXIT=0, no warning (ops::plan is pub(crate), as CondPlan is); byte-exact cargo test --release EXIT=0 (100 passed; its two warnings are the pre-existing CondPlan ones); the SOTA step on the regenerated vectors EXIT=0, the pretrained binary models decoding through the lowering to the export image eb1acd2159f8a966. Falsified, Part 3.5 row "rq rounding floor -> half_up in whm1/1": Red: int_hyper_ops EXIT=101 (the vector test: "tiny WIH1: StreamNoncanonical", since h_s's sigma moves the buckets; gate 1's graph bytes); byte-exact EXIT=101 with wih1_through_its_lowering_is_golden, wiv1_keyframe_1_through_its_lowering_is_golden and the_neural_keyframe_clip_through_its_lowering_is_byte_identical FAILED while the file-based wih1_payload_is_byte_identical and the_neural_keyframe_clip_is_byte_identical stay ok (pre-switch); splat's and audio's goldens FAILED too (switched). Restored. Row "igdn sums first, then shifts once": the tiny set survives it (int_hyper_ops EXIT=0, every byte-exact int_hyper golden ok) while the audio goldens FAIL, as Part 3.5 predicts for every set but audio; the pretrained set does carry it: the SOTA test EXIT=101, "the decode through the integer operator set must give the export image" d5763810e3fdef99 != eb1acd2159f8a966. Restored. Co-Authored-By: Claude Opus 5.5 <[email protected]>D2c M4, gate 3 (refusal parity). The registry export follows. - tests/int_hyper_ops.rs: (a) every committed fixture of both capabilities (33) is refused by a sink with its code; for each decode fixture (15) its WIH1, or its WIV1's keyframe, decodes through the lowering and directly to the same image, or is refused by both with the same code, the fixture's for WIH1; (b) 27 fixtures, one per refusal the direct decode makes, in integer- payloads §7's order, each one change from the committed tiny set or payload (the set against the payload, the networks planned and the caps, the shapes, each stream, each network's ranges); both decodes refuse each with the code §8 gives it; (c) at the edge of every check range of the committed h_s and g_s (six layers; the leaky ReLU followed by a zero 1x1 transposed convolution, since a network without a tag 0, 1 or 2 layer does not lower): at +-X_l both run alike, at +-(X_l + 1) both refuse (field_range at input 0; run_net_checked out of range at layer 0). - codecs::capability_ops: wai.neural.int_hyper and wai.video.int_hyper = {acc64, full, whm1/1, rans64 t4097/lenient/canonical, bucket ceil}; the registry unit test lists five capabilities. - SPEC §5's two rows cite integer-payloads §4 (§3 for the clip) and integer-operators §13.2; SPEC §7 names both; CHANGELOG section started. Co-Authored-By: Claude Opus 5.5 <[email protected]>D2c M4, gate 5 (fast-kernel parity), and M3's open item: the host lends the interpreter its fast inverse-GDN kernel. - int_ops::Host: an igdn operator runs on int_kernels::igdn (its narrow, 64-bit and 128-bit paths), declined back to the interpreter where, on the values present, a term or the norm could pass i128 or the root or output i64 (§13.2's P_l read on the actual values; no certified graph forms one), or gf or frac exceeds 127. - int_kernels: a test-only count of fast IGDN runs (testkit::fast_igdn_runs). - int_ops::equivalence: the_conditional_codec_runs_its_networks_on_the_fast_kernels (tiny: 4 convolutions and 1 inverse GDN on the fast kernels under every fast policy, 0 under the reference, the interpreter's bytes); inverse_gdns_equal_the_interpreter (int_transform's IGDN equivalence held to the interpreter: random gf, frac, gamma and beta of either sign, inputs on each of the kernel's three paths); whm1_convolutions_equal_the_interpreter (int_hyper_synth's kernel_equivalence held to the interpreter: WHM1's rq, strides to 16, i32/i64/mixed operands). The splat and audio tests now count their inverse GDNs on the fast kernel too. - tests/int_hyper_ops.rs: every_kernel_policy_decodes_through_the_lowering_alike (reference and fast(1|2|5|0) on WIH1, its JSON form, the JSON models, and sets with a hyper-latent channel about h_s's input range). Green (logs wai-build/logs/d2c-m4/g5): --lib int_ops debug and release EXIT=0 (9 passed); int_hyper_ops debug and release EXIT=0 (7 passed); byte-exact cargo test --release EXIT=0 (103 passed, the two pre-existing CondPlan warnings only). Gate 4's timed runs, on gate 4's tree (logs g4-timed*): 300 s per profile, seed 20261015, no disagreement, EXIT=0 both: debug 79,998 cases (12,560 alike; breaks bias 6,563 / unmeetable 47 / unused 3,969 / no tag 2,645), release 3,349,906 cases (529,718 alike; breaks 273,794 / 2,210 / 163,351 / 109,491). Falsified, M1's row for this gate (every channel requantised with channel 0's parameters, int_ops::conv): Red: --lib int_ops EXIT=101 (all three convolution equivalences, the new whm1 one included, and the three decoder tests); int_hyper_ops EXIT=101 (5 tests: the policy test, and, since the production policy is fast, the goldens, fixtures and range edges). Restored. Falsified, the IGDN arm (the fast IGDN given gf - 1): Red: --lib int_ops EXIT=101: inverse_gdns_equal_the_interpreter ("c=5 gf=24 frac=12" differs under fast(1)) and the conditional codec's, splat's and audio's decoder tests, while the three convolution equivalences stay ok; int_hyper_ops' every_kernel_policy_decodes_through_the_lowering_alike EXIT=101. Restored. Co-Authored-By: Claude Opus 5.5 <[email protected]>D2c M4, gate 6. - int_hyper_synth::decode_conditional_checked decodes through the integer operator set (ops::decode); the direct decode (legacy, with its run_net_checked wrapper) is cfg(any(test, feature = "legacy_int")). - int_payload: the WIH1 decode, the WIV1 keyframe and the declared cost run one pre-stream check (cond_checked) in integer-payloads §7's order: the plan, the keyframe's size against the clip's, then h_s and g_s lowered and loaded; the decode then runs from the loaded networks (ops::decode_loaded), holding the set as its networks and tables. - tests/int_payload_cost.rs: the conditional codec's set allowance is its tables and networks parsed, lowered and loaded; with them loaded beforehand, the decode must hold no more than the declared working bytes. - tests/int_hyper_ops.rs: the scan (every committed set of both capabilities meets the new load rules; every committed WIH1 payload, found by its magic in the conformance corpora, decodes through the lowering exactly as directly). - Text: integer-payloads §4 (h_s and g_s through whm1/1; the sigma/mu split a driver step after the shape check; the RGB8 step ends g_s's graph), §7 (the set rule; the order: shapes, then h_s and g_s lowered and loaded; for a WIV1 keyframe, its size before its networks' lowering; Exactness); integer-operators' status note and §15.3 item 3; SPEC §8; CHANGELOG. Green (logs wai-build/logs/d2c-m4/g6 and d2c-m4-g6, land/d2c-m4-g6): gate.sh d2c-m4-g6 GREEN (build, lib-tests, carriage, corpus loop 21/21, fast-kernels, byte-exact, wai-web wasm32 check, neural gates); the release fast-kernels step EXIT=0; int_hyper_ops EXIT=0 (8 passed, the scan included); int_payload_cost debug and release EXIT=0; cargo check --lib with neural_int alone and video_int alone EXIT=0, no warning; the SOTA step on the regenerated vectors EXIT=0, no skip banner; wai-ops debug and release EXIT=0; wai-verify vectors verify EXIT=0 (every file verifies); the Python checker EXIT=0; wai-web native EXIT=0; wasm32 release + wasm-bindgen 0.2.127 EXIT=0, and under Node: verify_int_payload_wasm (tiny WIH1 dce7282d…, video_nk 4a81f0c9…), verify_int_synth_wasm, verify_int_hyper_wasm on the pretrained set (eb1acd2159f8a966, the native hash) and verify_staged_wasm all EXIT=0. No tracked file changed by the builds. Memory: with its networks loaded beforehand, the tiny decode holds 16,470 bytes against 16,480 declared; the whole decode held 28,038, within the declared working bytes and the set's allowance. Falsified, row "rq floor -> half_up in whm1/1", the switch live: Red: byte-exact EXIT=101 with the file-based wih1_payload_is_byte_identical and wiv1_keyframe_1_payload_is_byte_identical FAILED (green under the same fault at gate 2) beside the through-the-lowering ones; --lib int_payload EXIT=101 (wih1_json_equivalence, wiv1_json_equivalence, decode_int_without_ neural …); tests/int_payload.rs EXIT=101; the corpus verify EXIT=1 ("FAIL tiny … stream_noncanonical", "FAIL video_nk …"). The unchecked neural_keyframe goldens stay green until gate 7 moves them. Restored. Falsified, the memory claim: the decode keeps a copy of its hyper-latent. Red: int_payload_cost EXIT=101, "int_hyper, set loaded: held 16534, declared 16480". Restored: 16,470. Co-Authored-By: Claude Opus 5.5 <[email protected]>ca79392a, with #264, #265 and #263) into wai/d2c-m4