Conversation
This was referenced Sep 18, 2026
Closed
lusoris
force-pushed
the
port/upstream-2026-09
branch
from
September 19, 2026 21:04
5ad4972 to
a44c65c
Compare
lusoris
force-pushed
the
fix/adm-cm-simd-bitexact
branch
from
September 19, 2026 21:23
6c3b0e8 to
9f9147a
Compare
added 3 commits
September 19, 2026 23:31
The scale-0 masking threshold adds a centre tap of (int16_t)(((ONE_BY_15 * abs(a)) + 2048) >> 12). For |a| above about 15360 the shifted value no longer fits int16, and the scalar reference, which is upstream Netflix/vmaf's C, wraps it. The AVX2 and AVX-512 vector threshold macros kept the 32-bit value (their scalar edge macros did wrap), so the SIMD paths drifted from scalar wherever the CSF-weighted band gets that large: 576x324 full-range noise by 2.1e-4 in integer_adm_scale0, a 64x64 high-contrast ramp by 7.2e-4. Each vector tap is now sign-extended from its low 16 bits, which is the (int16_t) conversion. AVX2 and AVX-512 equal scalar on those inputs. Scalar scores do not change, and neither do SIMD scores on the three Netflix golden pairs or the akiyo multiply pair, which never reach the wrap. New test_integer_adm_simd_noise scores independent full-range noise at three sizes with the default dispatch and with AVX2 alone against scalar. It fails at 96x64 with the old macros, and passes on NEON under QEMU.
lusoris
force-pushed
the
fix/adm-cm-simd-bitexact
branch
from
September 19, 2026 21:36
9f9147a to
918175d
Compare
12 tasks
Contributor
Author
|
Absorbed into the ADM stack train #1507, per your direction to fold this stack the way #1506 was folded. This PR targeted the one below it in a five-deep stack, so none of the five could merge until every one below had merged and been restacked — five sequential rebase-plus-CI rounds. #1507 is one. Your work is in it unchanged; that PR's description lists the six defects the fold itself surfaced, none of which an individual PR could see, because each gate only looks at the files its own PR touches. The branch stays on the remote. |
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.
Summary
The AVX2 and AVX-512 integer ADM paths gave slightly different scores from the scalar path on content with very large band coefficients, such as full-range noise. They now match scalar bit for bit. Stacked on #1473; review that first.
The scale-0 contrast-masking threshold adds a centre tap of
(int16_t)(((ONE_BY_15 * abs(a)) + 2048) >> 12). For|a|above about 15360 the shifted value no longer fits int16, and the scalar reference (which is upstream Netflix/vmaf's C) wraps it. The vector threshold macros inadm_avx2.candadm_avx512.ckept the 32-bit value; their own scalar edge macros did wrap. So the SIMD paths drifted from scalar exactly where the CSF-weighted band gets that large.The fix sign-extends each vector tap from its low 16 bits (
srai(slli(x, 16), 16)), which is what the(int16_t)conversion does.Scalar scores do not change. SIMD scores on ordinary video don't either, because it never reaches the wrap; the golden pairs above are byte-identical before and after. Upstream's AVX2 and AVX-512 have the same macros.
This closes
T-ADM-CM-SIMD-NOISE-NOT-BIT-EXACT-2026-09-18, which #1473 opened.Type
feat— new featurefix— bug fixperf— performance improvementrefactor— no behavior changedocs— documentation onlytest— test-onlybuild/ci— tooling / infraport— cherry-pick from upstream Netflix/vmafsycl/cuda/simd— backend-specificChecklist
make format && make lintis green locally.meson test -C build./cross-backend-diffand the worst ULP is ≤ 2: integer path, now bit-exact with scalar on AVX2 and AVX-512 (table above); NEON unchanged and bit-exact under QEMU.adm_cmkernel (scalar runs there). On the same noise the CUDA and HIP twins already match scalar (5e-8 and 0); the SYCL twin skips the same 16-bit truncations and drifts by 2.1e-4, which the stacked GPU PR (fix/gpu-adm-tiny-frames) fixes..c/.cpp/.cu/.h/.hpp, it has the appropriate license header (seeCONTRIBUTING.md).!orBREAKING CHANGE:and the migration path is documented below: not breaking.docs/adr/_index_fragments/<NNNN-slug>.mdand the slug is appended todocs/adr/_index_fragments/_order.txt: no ADR, a bug fix.Bug-status hygiene (ADR-0165)
docs/state.md:T-ADM-CM-SIMD-NOISE-NOT-BIT-EXACT-2026-09-18moves to Recently closed with the cause and the fix.Netflix golden-data gate (ADR-0024)
assertAlmostEqual(...)score in the Netflix golden Python tests.Deep-dive deliverables (ADR-0108)
docs/research/2063-upstream-sync-2026-09-adm-vif-simd.md, open-questions entry updated with the cause.core/src/feature/x86/AGENTS.md.changelog.d/fixed/adm-cm-simd-int16-wrap.md.docs/rebase-notes.md: keep the wrap when a sync touches the vector threshold macros.Reproducer
ref.yuv/dis.yuv: any two independent full-range 8-bit noise clips.Verified locally
test_integer_adm_simd_noisescripts/dev/preflight.sharm64/adm_neon.cand the x86 SIMD files, which the i686 lane never builds (-Denable_asm=false), and misreads gcc's missing-header message underLC_ALL=C;check_exported_symbolsflags ASan's__start_asan_globals/__stop_asan_globalsunder GNU ld (CI links with lld)Known follow-ups