One squashed history of three stacked PRs, onto main atb16816671: - #426 (wai/pack-efficiency): a title's whole AV1 ladder in one package over one integer base; several floor rungs (packaging §7.1), a re-pack from a parent (§11.5), a floor that is the ladder's own CMAF (§7.7), a floor-only profile (§7.8), a streaming pack (§11.4), and the independent verifier at scale (§9.4). - #438 (wai/cross-fabric): each pack and verify step on the fabric with the least measured energy (§11.6); the `fabrics` member of measurement claims (jwp-receipts §2.4.8, energy-measurement §6.3); the wai-pack-gpu crate; `wai-pack fabric`; `wai-pack floor-decode`. - #452 (wai/gpu-int-tier), its GPU-tier part only: claiming decode-equivalence on a GPU (determinism-tiers §5), the WGSL integer semantics suite, the rules check on naga's IR, and the kernels' shift masks and min(max()) clamps. Left out, by the review's split (EN-C takes it over): #452's platform decode in dispatch, its commits6ad92e2e8,8695bc75fandfed8694f4and its CHANGELOG entry: extensions/platform-decode.md, platform-decode-conformance/, wai::platform_decode, wai-web's platform_decode bundle and demo, and its two SPEC.md sentences. #438's research note is not carried as written: it is rewritten as wai/research/cross-fabric.md, with hardware named by architecture, PCI id and OS version, and every table marked as one run. floor_decode.rs and a wai_pack.rs comment name the platform's media engine and a full-length film the same way. wai/CHANGELOG.md is the union of both sides' entries, the stack's first. Co-Authored-By: Claude Opus 5.5 <[email protected]>
339 lines
24 KiB
Markdown
339 lines
24 KiB
Markdown
# WAI across fabrics: research for the packer and the verifiers
|
||
|
||
> **Status.** Research note, informative, not normative. It records what decided the change
|
||
> that lets each step of a WAI pack or verify run on the fabric that does it with the least
|
||
> measured energy (the CPU, a GPU, a hardware media engine, or a neural processor):
|
||
> [packaging](../extensions/packaging.md) §11.6, [jwp-receipts](../extensions/jwp-receipts.md)
|
||
> §2.4.8 and [energy-measurement](../extensions/energy-measurement.md) §6.3. Nothing here changes
|
||
> a byte of a package or a verdict.
|
||
|
||
**Method.** Every statement about an interface or a specification was checked against that
|
||
document on 2026-10-22. Items marked **[measured]** were run for this note (the setup is in §9);
|
||
items marked **[local]** were read from the platform's SDK headers on the machine that ran them.
|
||
Exact counts and digests are exact. Times and energies are indicative: each table in §9 is **one
|
||
run**, on a shared host whose load is given, and none is a sample of anything.
|
||
|
||
## 1. The hardware the measurements ran on
|
||
|
||
Hardware is named as the rest of the repository names it: by architecture, PCI vendor and device
|
||
id, and operating-system version.
|
||
|
||
- **arm64 desktops** (macOS 27.0.1), each with an integrated GPU and a media engine that decodes
|
||
AV1 in hardware and encodes no AV1. The measurements of §9 ran on one of them, shared with other
|
||
work. Every one reports the platform's current GPU interface.
|
||
- **A Windows x86_64 host** with an integrated GPU of PCI vendor 0x8086, device 0x9a49, and a
|
||
discrete GPU of PCI vendor 0x10de, device 0x1f15. Its vendor's published support matrix gives
|
||
that discrete GPU's architecture neither AV1 decode nor AV1 encode; the integrated GPU decodes
|
||
AV1, with a film-grain path its vendor does not state as bit-exact (§6.1).
|
||
- **Linux x86_64 hosts** with GPUs of PCI vendor 0x10de, device 0x28e1, of vendor 0x8086, device
|
||
0xa7a0, and of vendor 0x1002, device 0x1586, as determinism-tiers §5 records them. Their media
|
||
engines were not probed for this note.
|
||
|
||
## 2. The steps, and the fabrics that can run each
|
||
|
||
| Step | CPU | GPU | Media engine | Neural processor | Placed on |
|
||
|---|---|---|---|---|---|
|
||
| `source-decode` (a coded source to frames, before a pack) | dav1d | | AV1 decode where the engine has it | | either, on equal pictures (§6) |
|
||
| `source-read`, `segment` | yes | | | | CPU (sequential, cheap) |
|
||
| `base-search` (the integer motion search) | reference | exact integer kernel | none: no engine runs §5.5's search, and the platform's hardware motion estimation is not it (§3) | unsound (FP16, §5) | GPU where it qualifies |
|
||
| `base-code`, `refine-code` (residuals, rANS) | reference | | none: no engine codes `WIV1` or `WIR1` | | CPU (rANS is sequential) |
|
||
| `sse` | reference | exact (partial sums under 2^32) | | unsound | by measured cost |
|
||
| `object-hash` (BLAKE3) | reference | exact (chunks on the device, parents on the host) | | | by measured cost |
|
||
| `digest` (SHA-256) | yes | no: one message is one chain (FIPS 180-4 §6.2.2) | | | CPU |
|
||
| `floor-read` (AV1 and CMAF structure) | yes | | | | CPU |
|
||
| `floor-decode` | dav1d | | AV1 decode, as above | | informative only (§6.3) |
|
||
| `index`, `io` | yes | | | | CPU |
|
||
|
||
What this decides: the GPU takes the one step that dominates a pack's work, the motion search (at
|
||
least 96.8% of the CPU-only pack's CPU time in the run of §9.2), plus SSE and BLAKE3 where the
|
||
measured cost says so, which on the host of §9 it does not (§9.3). No hardware encoder computes any
|
||
WAI step. The media engine decodes AV1 sources and floors. The neural processor computes nothing
|
||
exact.
|
||
|
||
## 3. Media engines
|
||
|
||
- **AV1 decode, and no AV1 encode, on the arm64 desktops.** Every published specification of their
|
||
media engines lists AV1 decode and no AV1 encode, and the platform's compression headers name no
|
||
AV1 encoder **[local]**. ffmpeg's encoders for the platform's framework cover H.264, HEVC and
|
||
ProRes only.
|
||
- **What the decode needs.** A decode session takes the sequence header OBU from an `av1C` record;
|
||
a low-overhead OBU stream (`-f obu`) gives it none up front, so it does not decode there, while
|
||
the ladder's CMAF (with `av1C`) does **[measured]**. The reference tool therefore decodes floors
|
||
from the package's CMAF files.
|
||
- **What it gives back [measured]** (ffmpeg 9.0.2, macOS 27.0.1):
|
||
- The ladder of §9 is AV1 Main profile, **10-bit** (each rung's `av1C`). The engine's hardware
|
||
frames are P010; a download as 8-bit NV12 is refused.
|
||
- Its raw P010 frames equal, frame by frame, dav1d's planar 10-bit output repacked to P010. But
|
||
ffmpeg's P010-to-8-bit conversion of them does not equal dav1d's own 10-to-8-bit conversion:
|
||
that conversion rounds and dithers, so a comparison stays at the stream's bit depth or
|
||
converts exactly.
|
||
- Earlier comparisons hashed `-f framemd5` outputs with stderr piped into the hash; the
|
||
"difference" they showed was ffmpeg's error text. Every comparison in §9 hashes the output
|
||
file, not the console.
|
||
- **Hardware motion estimation.** The platform offers a motion-estimation session returning 4×4 or
|
||
16×16 vectors, and documents neither the engine, its cost metric, its search window nor its
|
||
determinism. It cannot compute §5.5's normative search.
|
||
- **Other platforms.** One vendor's published support matrix gives AV1 decode from one GPU
|
||
generation and AV1 encode from a later one, and states that its decoder runs independently of
|
||
the compute engine. Another's media driver decodes AV1 from its twelfth graphics generation, in
|
||
its full-feature build. A third's kernel driver decodes AV1 on its third video-core generation
|
||
and encodes from its fourth. Vulkan defines `VK_KHR_video_decode_av1` from Vulkan 1.3.277 and
|
||
`VK_KHR_video_encode_av1` from 1.3.302.
|
||
|
||
## 4. GPU compute
|
||
|
||
- **WGSL integer semantics** (WGSL, W3C Candidate Recommendation Draft): `i32` operations "use
|
||
two's complement arithmetic and have defined overflow behavior"; `>>` on a signed value inserts
|
||
copies of the sign bit (§8.10); an integer division by zero evaluates to `e1` (§8.8); an
|
||
out-of-bounds access is a dynamic error the implementation does not perform as written (§6.5.7).
|
||
So a WGSL kernel that keeps every value inside its type and every index inside its buffer has
|
||
one result on every conformant device. The WAI kernels do: a block's cost is at most
|
||
`block² · 765`, refused on the host where that passes 2^32 − 1. What a translator does with the
|
||
cases WGSL defines and its target languages do not is determinism-tiers §5's subject.
|
||
- **The backend languages.** MSL leaves signed integer overflow undefined and its atomics relaxed,
|
||
so only commutative integer reductions are order-free there. The WAI kernels use no atomics:
|
||
each block's minimum is a tree reduction over a total order, so it does not depend on which
|
||
thread visits which candidate.
|
||
- **BLAKE3 on GPUs.** The specification splits input into 1 KiB chunks hashed independently.
|
||
Published GPU ports measured slower than one CPU core on a discrete GPU, or than eight CPU
|
||
threads on an integrated one, and none reported energy. Measured here in §9.3.
|
||
|
||
## 5. Neural processors
|
||
|
||
The neural processor of the arm64 desktops computes in FP16, which the platform's machine-learning
|
||
framework can permit but not require, and its documentation states that its capabilities differ by
|
||
hardware and software generation. FP16 represents integers exactly only up to 2048, and one 8-bit
|
||
squared difference is 65025. **No WAI step can run on it.** The fabric term is `npu`, the term
|
||
determinism-tiers uses for `wai-ops/1-npu`.
|
||
|
||
## 6. Determinism and conformance
|
||
|
||
### 6.1 AV1 decoding is exact, film grain aside
|
||
|
||
AV1 Bitstream & Decoding Process Specification, Version 1.0.0 with Errata 1, §7.2: "When
|
||
film_grain_params_present is equal to 0, decoders shall produce output frames that are identical
|
||
in all respects and have the same output order as those produced by the decoding process
|
||
specified herein." With film grain, a conformant decoder may instead match only the pre-grain
|
||
frames of §7.18.2 and add grain with no "perceptually significant differences". dav1d states that
|
||
it passes the AV1 conformance streams with grain on. One GPU vendor's media driver states that its
|
||
film-grain path does not guarantee a bit match, and AV1 decode defects have been fixed in more than
|
||
one vendor's driver.
|
||
|
||
**Tested [measured]:** the media engine decoded each rung of the ladder of §9, and its pictures
|
||
were compared with dav1d's (§9.1). The ladder carries no film grain: dav1d gives the same frames
|
||
with grain applied and with it exported.
|
||
|
||
### 6.2 Hardware encoders are not reproducible
|
||
|
||
No vendor states that its hardware encoder is deterministic. One vendor's encoder guide documents
|
||
split-frame encoding that turns on with the number of engines and the frame height, and another's
|
||
low-power AV1 rate control runs in firmware. Software encoders are reproducible only under pinned
|
||
conditions.
|
||
|
||
### 6.3 What it means for WAI
|
||
|
||
- **Receipts.** A package's bytes do not depend on where its steps ran, because every step is
|
||
integer and the GPU kernels compute the same integers: the receipt, the index and every object
|
||
are the CPU's (§9.1). Where the steps ran is recorded only in a metered package's measurement
|
||
claim, which §11.2 already exempts, so an unmetered package records nothing machine-specific.
|
||
- **§11.2 on non-deterministic hardware.** No WAI step may be computed by a hardware encoder. A
|
||
floor a packager is given is an input; a floor encoded on a hardware encoder is one §7.5 covers,
|
||
and §11.2 does not hold its bytes.
|
||
- **Verifiers' independence.** A check whose expected value the package states (an object's
|
||
content hash) may run anywhere: a match shows the fabric computed it, and a mismatch is computed
|
||
again on the CPU before it is reported. A floor states no decoded-output digest, so a hardware
|
||
decode never decides a floor verdict, and a hardware decoder may conceal an error that dav1d
|
||
reports. The Python verifier stays on the CPU and shares no code with wai-rs; the GPU path is
|
||
wai-pack's.
|
||
|
||
## 7. Measuring energy per fabric without privileges
|
||
|
||
### 7.1 macOS 27
|
||
|
||
- **IOReport** is a private interface (the SDK ships a stub and no header **[local]**). On macOS 27
|
||
its Energy Model CPU and neural-processor channels stay visible and stop updating for a reader
|
||
without a private entitlement. **[measured]** on the host of §9: of 645 Energy Model channels,
|
||
only `GPU Energy` (nJ) moved over a 6 s span during a hardware decode, a dav1d decode and idle;
|
||
the CPU, per-core, neural-processor, video-encoder, memory and display channels read zero, and
|
||
there is no decoder energy channel. So **the media engine and the neural processor have no
|
||
unprivileged counter there**; a privileged sampler reads the neural processor, and nothing in
|
||
this change runs privileged.
|
||
- **CPU, per process:** `proc_pid_rusage(RUSAGE_INFO_V6)` gives the kernel's account of the task's
|
||
own CPU energy (`ri_energy_nj`) and the energy it billed to the task and serviced for others
|
||
(`ri_billed_energy`, `ri_serviced_energy`), readable for one's own process or a child. A task's
|
||
`task` share is `ri_energy_nj + ri_billed_energy − ri_serviced_energy`, the definition the
|
||
sink-metering profiles use, so energy a system service spent for the process is in it. Other
|
||
load on the host enters it only through contention.
|
||
- **GPU, per process:** the accelerator's user clients in the I/O registry carry each creator's pid
|
||
and its accumulated GPU time (ns), readable by any process **[measured]**. The repository's own
|
||
measurement found that dividing the shared rail by GPU time charged a decode 3 to 15 times its own
|
||
GPU energy, and that a client disappears with its process. So the rail is attributed to a process
|
||
only when it was the rail's sole user: the clients are sampled every 200 ms through the span, each
|
||
client's GPU time differenced between samples, and the span refused when a client vanishes, a
|
||
difference is negative, or the process held under 99% of the GPU time the samples saw. The rail
|
||
is then sealed whole, its idle and static draw over the span included, never divided by busy
|
||
time. The rail holds a reading for hundreds of milliseconds and then catches up in one step, so
|
||
it is read on its next republish at each end, inside the sampled window.
|
||
|
||
### 7.2 Linux and Windows (not run here)
|
||
|
||
- RAPL's `energy_uj` became root-only in Linux 5.10, and perf's RAPL events are system-wide only,
|
||
so reading CPU energy there takes an owner's act (`cap_perfmon`, or a group-readable
|
||
`energy_uj`).
|
||
- NVML's total-energy query (mJ) is not marked as needing privilege; the in-kernel hwmon power and
|
||
energy attributes of two other GPU drivers are world-readable.
|
||
- Windows' Energy Meter Interface is readable unelevated.
|
||
|
||
## 8. The design choices, and what decided them
|
||
|
||
| Choice | Decided by |
|
||
|---|---|
|
||
| The GPU computes the motion search, SSE and BLAKE3 chunks, in WGSL integer kernels through wgpu, not in one platform's shading language | WGSL's defined integer arithmetic (§4) gives one result on every conformant device; the repository's GPU precedent (`wai-ops-gpu`) is wgpu. Exactness is claimed only on the adapters a run showed (`wai-pack-gpu`'s crate documentation lists them), with qualification at open as the runtime gate |
|
||
| A backend runs a step only after it gives the reference's output on qualifying inputs; any call it cannot take runs on the CPU | §11.2 must hold on every fabric; a device or driver can be wrong (§6.1's driver defects) |
|
||
| Placement by a measured cost table (µJ per call + nJ per unit), the CPU on a tie or where unmeasured | **[measured]** the GPU's fixed cost per call (1.7 mJ for a hash, 3.1 mJ for an SSE) exceeds what a pack's calls save, while the search saves 14× per unit (§9.3); placing by fabric alone made the floor-only pack dearer (§9.2) |
|
||
| The fabric record lives in the measurement claim, not the receipt | the receipt and `LISTING` would otherwise differ by machine, voiding §11.2 for every package; the claim is already §11.2's exemption |
|
||
| `fabrics` is absent rather than `null` | every existing claim, and every package that carries one, keeps its bytes |
|
||
| Attributions `task` and `rail` only; a `rail` share is the whole rail, sealed only for its sole user | the repository's measurement of a 3–15× overcharge from dividing by busy time (§7.1) |
|
||
| The figure is an `OnChipCounter` reading with a declared uncertainty over its span | both readings are counters (energy-measurement §2, §2.9); a counter reading is not a model |
|
||
| Hardware AV1 decode for sources and for informative floor decodes; never a floor verdict | AV1 §7.2 (exact without grain); floors state no digest; hardware may conceal errors |
|
||
| Hardware frames read from P010 exactly, never through ffmpeg's 16-to-8-bit conversion | **[measured]**: that conversion differs from dav1d's (§3) |
|
||
| No hardware encoder computes a WAI step | §6.2 |
|
||
| No neural-processor backend | §5 |
|
||
|
||
## 9. Measurements
|
||
|
||
**Setup.** A 596 s, 24 fps open-licence film, 14,315 frames: a 256×144 integer proxy and the
|
||
ladder's four 10-bit AV1 rungs (1080, 720, 540 and 360 lines). One arm64 desktop (macOS 27.0.1),
|
||
shared with other work; each run's load average is in its report. wai-pack at this change,
|
||
release, features `gpu,fabric-meter`; ffmpeg 9.0.2 with dav1d 1.5.4. Each run was metered by an
|
||
external sampler that read the kernel's account of the child's CPU energy before reaping it (and of
|
||
every decode service the run started: hardware decodes run out of process, and a 2,000-frame
|
||
decode billed 1.20 J to ffmpeg and 1.09 J to its service), and the IOReport `GPU Energy` rail and
|
||
every client's GPU time every 200 ms, with idle brackets before and after.
|
||
|
||
**Class and scope of every figure below.** CPU figures are `OnChipCounter` readings of the
|
||
process's own task energy. GPU figures are `OnChipCounter` readings of the whole GPU rail over the
|
||
run, given only where the run held at least 99% of all GPU time; otherwise there is no GPU figure.
|
||
The media engine has no counter, so a media-engine run's figure is its CPU side alone, a lower
|
||
bound. **Each table is one run.** None was repeated, so none is a median, and none carries a
|
||
measured spread; they are indicative.
|
||
|
||
### 9.1 Exact results
|
||
|
||
- **Packages are the same bytes on the GPU.** A 360-line rung's policy packed with
|
||
`--fabric gpu`: the CPU pack's digest (`7454acc6…1118`), every file the same (`diff -r`), in
|
||
three runs, and with `--fabric auto:<costs>` too. A four-rung pack over the ladder's own CMAF,
|
||
the base coded once: pack digest `3912bd7c…b9b7f` and receipt `e0256cd9…`, the CPU's. A
|
||
floor-only pack: `f8871444…e032`, the CPU's.
|
||
- **The media engine decodes what dav1d decodes.** Each of the four rungs, all 14,315 frames: the
|
||
SHA-256 of every frame in P010 equal between the engine's hardware frames and dav1d's output.
|
||
And `wai-pack floor-decode` of the four-rung package: the same digest from both decoders for each
|
||
of its 600 pieces, in the stream's own 10-bit form, the P010 words read back exactly.
|
||
- **A source decoded by the media engine is the same source.** The proxy decoded from the 1080-line
|
||
rung on the engine, then by the same scaler: SHA-256 `8d236f5b…b56d`, the CPU decode's proxy byte
|
||
for byte.
|
||
- **Placement.** In a 12-piece pack, 24,915 of 24,930 motion-search calls ran on the GPU before the
|
||
map-wait fix. The other 15 were handed back to the CPU, with the same vectors.
|
||
- **Instructions.** The CPU-only 360-line pack retired 98.3 × 10¹² CPU instructions; the GPU pack
|
||
retired 2.05 × 10¹².
|
||
|
||
### 9.2 Pack and verify, joules per fabric (one run each)
|
||
|
||
The GPU's other clients held under 1% of its time in every pack of this run.
|
||
|
||
| Run | Wall | CPU (task) | GPU (rail) | Total | Peak memory | CPU-only baseline (task) |
|
||
|---|---:|---:|---:|---:|---:|---|
|
||
| 360-line pack, search on the GPU | 56 s | 573 J | 1,284 J | **1,857 J** | 0.95 GB | 20,299 J, 3,689 s, 3.04 GB |
|
||
| 360-line pack, `auto` (search on the GPU; SSE and hashes on the CPU) | 56 s | 571 J | 1,283 J | **1,854 J** | 0.76 GB | as above |
|
||
| four-rung CMAF pack, search on the GPU, `--jobs 12` | 71 s | 525 J | 1,239 J | **1,763 J** | 1.62 GB | 19,541 J, 980 s at `--jobs 6`, 0.17 GB |
|
||
| floor-only pack, hashes on the GPU | 2.2 s | 4.4 J | 2.3 J | **6.7 J** | 0.65 GB | 3.7 J, 1.5 s, 0.04 GB |
|
||
| `wai-pack verify`, 360-line, CPU | 32 s | 118 J | 0 | 118 J | 0.58 GB | 31–33 s |
|
||
| `wai-pack verify`, 360-line, hashes on the GPU | 31 s | 120 J | none (GPU shared) | ≥ 120 J | 2.04 GB | |
|
||
| `wai-pack verify`, four-rung, CPU | 34 s | 119 J | 0 | 119 J | 1.55 GB | 35 s, 121 J |
|
||
| `wai-pack verify`, four-rung, hashes on the GPU | 32 s | 122 J | 0.2 J | 122 J | 3.44 GB | |
|
||
|
||
What the table shows:
|
||
- Moving the motion search to the GPU cut the 360-line pack's energy 9 to 11 times over the two
|
||
runs made: 1,857 J here and 2,248 J in the sealed run of §9.5, against a 20,299 J baseline. The
|
||
baseline is CPU task energy alone, and the GPU runs add the whole rail. The CPU work left
|
||
(residuals, rANS, digests, I/O: 116 s of CPU against the baseline's 3,635 s) shows that the
|
||
search was at least 96.8% of the baseline's CPU time.
|
||
- Moving the object hashes or SSE gained nothing: the floor-only pack, whose only movable step is
|
||
hashing, cost more on the GPU.
|
||
- `wai-pack verify` is dominated by the integer base's decode, which is sequential rANS, so it
|
||
stays on the CPU.
|
||
|
||
### 9.3 The measured cost table (`wai-pack fabric calibrate`, one run)
|
||
|
||
Each backend, two call sizes, 6 s each, fitted to `µJ per call + nJ per unit`:
|
||
|
||
| Step | CPU | GPU | Placement |
|
||
|---|---|---|---|
|
||
| `base-search` (unit: candidate-sample) | 0 + 20.2 nJ | 11,276 µJ + 1.47 nJ | GPU from about 600,000 units, a 32×24 frame at the policy's range; every frame of the film is 32 million |
|
||
| `sse` (unit: byte) | 0 + 0.85 nJ | 3,136 µJ + 0.76 nJ | CPU below about 35 MB a call; a piece of the film is 5 MB |
|
||
| `object-hash` (unit: byte) | 7 µJ + 1.33 nJ | 1,699 µJ + 1.43 nJ | CPU always: the GPU's BLAKE3 is no cheaper per byte either |
|
||
|
||
The GPU's per-call cost includes its idle and static draw over the call, since the rail is the whole
|
||
GPU's.
|
||
|
||
### 9.4 Decoding: CPU against the media engine (one run)
|
||
|
||
The decode service was counted; the GPU was shared in this run, and no decode used it.
|
||
|
||
| Decode of the whole floor | dav1d: wall, CPU | media engine: wall, CPU (ffmpeg and its service), engine |
|
||
|---|---|---|
|
||
| 1080 lines | 23.1 s, 198.7 J | 22.0 s, 17.4 J, + unmetered |
|
||
| 720 lines | 12.4 s, 111.0 J | 17.3 s, 11.3 J, + unmetered |
|
||
| 540 lines | 7.7 s, 73.3 J | 14.1 s, 8.5 J, + unmetered |
|
||
| 360 lines | 5.1 s, 53.8 J | 11.3 s, 15.9 J, + unmetered |
|
||
| proxy source (1080 lines decoded and scaled to 256×144) | 22.7 s, 304.1 J | 25.6 s, 350.5 J, + unmetered |
|
||
|
||
What the table shows:
|
||
- A floor decode on the media engine cost the CPU 8 to 11 times less at 540 to 1080 lines, and 3.4
|
||
times less at 360, where the per-frame download dominates.
|
||
- The engine's own draw is not visible to an unprivileged reader on macOS 27 (§7.1), so these are
|
||
lower bounds.
|
||
- For the proxy source the engine saved nothing: the Lanczos scale and the P010 repack on the CPU
|
||
cost more than the decode saved. Placing `source-decode` on the media engine is worth it only
|
||
where the scaling also moves, and moving it would change the source's bytes unless the scaler is
|
||
exact.
|
||
|
||
### 9.5 A metered pack, sealed (one run)
|
||
|
||
- **Sealed.** The 360-line pack with `--fabric gpu --meter fabric`, run when the GPU's other
|
||
clients had held under 0.5% of its time over the preceding 10 s, sealed 2,248.4 J with the fabric
|
||
record in its measurement claim: the CPU's share 475.4 J (`task`) and the GPU's 1,773.0 J
|
||
(`rail`, the pack its sole user); the steps `base-search`, `sse` and `object-hash` on the GPU and
|
||
every other step on the CPU, with no search call handed back to the CPU.
|
||
- **Which meter.** That run used the meter's first revision, which sealed the figure as
|
||
`ModelBased`, took the GPU's time at the two ends only, and multiplied the rail by the pack's
|
||
share of GPU time (at least 99%). The meter now seals `OnChipCounter` with the whole rail and
|
||
samples GPU time through the span (§7.1). The run has not been repeated under it, so its figures
|
||
are the first revision's.
|
||
- **Verified.** `wai-pack verify` accepts the package, and `pack_verify.py` holds every check of it
|
||
(3622 of 3622), the claim among them.
|
||
- **Refused.** The same metered four-rung pack, a minute later, found the GPU shared (39.9 s of its
|
||
50.0 s) and was refused `pack-meter`, as was the calibration then.
|
||
|
||
### 9.6 Load, and what is indicative
|
||
|
||
- The host's one-minute load average was 14 to 50 over the runs of §9.2 and 25 to 90 over §9.4.
|
||
- The CPU figures are each process's own, by the kernel's attribution, so other load changes them
|
||
only through contention.
|
||
- The GPU figures of §9.2 are from a run that held the GPU alone. In the run of §9.4 another process
|
||
held about a third of the GPU's time; the GPU packs then had no GPU figure, and the metered packs
|
||
were refused `pack-meter` ("the GPU was shared: this process had 45.2 s of its 65.0 s, under
|
||
99%").
|
||
- Instruction counts and digests are exact.
|
||
|
||
## 10. Judged unsound
|
||
|
||
- **Any WAI step on the neural processor** (§5).
|
||
- **A hardware encoder for any WAI step:** floors are supplied, the packer refuses to encode one
|
||
(`pack-floor-encode-unsupported`), and no hardware encoder's bytes are reproducible (§6.2).
|
||
- **The platform's hardware motion estimation in place of §5.5's search** (§3).
|
||
- **Dividing a shared GPU rail by GPU time** (§7.1).
|
||
- **Media-engine and neural-processor energy on macOS 27 without privileges:** no live counter
|
||
(§7.1); a step run there makes a metered span refuse rather than guess.
|
||
- **A floor verdict from a hardware decoder** (§6.3).
|
||
- **ffmpeg's P010-to-8-bit conversion in a comparison** (§3).
|