test: one model, one snippet, two profiles, two forms, both correct - #1125
Merged
Merged
Conversation
Closes #1118. Slice 5 of #1109. The acceptance criterion for the whole of #1109: a model author writes nothing about weight forms, and the same code is correct on a workstation and on a 2 GB board because the resolver answered differently. The test is arranged so that claim is falsifiable — `userCode` takes a weight and an activation, no profile, no form, no policy, and is called identically on both paths. If honouring a device ever required the caller to say something, this file would have to change to keep passing. It found two things before it asserted anything. Slices 1 and 2 disagreed. The resolver asked for KERNEL_FEED in the common case of a target that has kernels, and the loader rejected it pending #1120 — neither slice's own tests could see this, only running them together could. Wanting feed order is a fact about the kernel; producing it is a fact about whoever writes the bytes, and collapsing the two is what let slice 1 emit a form nothing could honour. The resolver now takes canProduceKernelFeedOrder, false until #1120 makes it true. And a pre-existing silent correctness bug, filed as #1124: the common DefaultCpuOps computes packed matmul wrongly when the KernelRegistry is empty. Chasing an output mismatch of 12.94 vs -71.34 established that the weight's own toFloatArray() agreed with the dense path and not with the packed one. The test registers ScalarKernelProvider, as every PlatformCpuOpsFactory does at startup, so it runs in the configuration a real application runs in rather than in the broken one. Gate: scripts/pr-gate.sh — all legs passed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
📖 Documentation Preview The documentation has been built successfully for this PR. Generated Files:
Artifacts:
This comment will be updated automatically when the PR is updated. |
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1118. Slice 5 of 5 for #1109.
The acceptance criterion for the whole thing: a model author writes nothing about weight forms, and the same code is correct on two very different devices.
Everything else in #1109 is machinery for that one claim, so the test is arranged to make it falsifiable rather than to exercise the machinery:
No profile, no form, no policy. Called identically on both paths. If honouring a device ever required the caller to say something, this file would have to change to keep passing.
Desktop resolves to
KeepAsStored+HEAP; the 2 GB board toDequantizeTo(FP32)+MAPPED. Asserted to be different, then asserted to agree numerically within quantization error — not bit-identical, and the test says why: one path multiplies through a Q8_0 kernel and the other through dequantized floats.It found two problems before asserting anything
Slices 1 and 2 disagreed. The resolver asked for
KERNEL_FEEDin the common case — a target that has kernels — and the loader rejected it pending #1120. Neither slice's own tests could see this; only running them together could.The fix is that wanting feed order and being able to produce it are facts about different components.
KernelCapabilities.wantsKernelFeedOrderanswers the kernel's half; the newcanProduceKernelFeedOrderparameter answers the loader's, and isfalseuntil #1120. Collapsing them into one is what let slice 1 hand slice 2 a form it had to reject.A pre-existing silent correctness bug — #1124. An output mismatch of
12.94vs-71.34was too large for quantization error. The weight's owntoFloatArray()agreed with the dense path and not with the packed one, which narrowed it to: the commonDefaultCpuOpscomputes packed matmul wrongly when theKernelRegistryis empty.DefaultCpuOpsJvmDefaultCpuOps(common)DefaultCpuOps(common)Not caused by this work, and not fixed here. The test registers
ScalarKernelProvider— what everyPlatformCpuOpsFactorydoes at startup — so it runs in the configuration a real application runs in, with a comment saying so and pointing at #1124.The other two tests
The mobile plan knows what its form costs before the load (#1116's pricing, end to end), and a
strictboard is told about a missing kernel instead of quietly paying 4× for it —MOBILE_2GB's own documentation calls dispatcher-inserted dequantization "the defect it is".Build change
skainet-io-gguf's jvmTest gainsskainet-backend-cpuandskainet-backend-api. Test-only, and not a cycle — the CPU backend does not know about GGUF. This module's ownDefaultDataExecutionContextcarriesVoidTensorOps, and an acceptance test that loads a model has to actually run it.Gate
scripts/pr-gate.sh— all legs passed.🤖 Generated with Claude Code