Skip to content

quantize: optimize QuantizeBlockNEON with 2x unrolling and streamlined zigzag loop - #194

Merged
skal65535 merged 1 commit into
mainfrom
skal/quant-neon
Sep 21, 2026
Merged

skal65535 merged 1 commit into
mainfrom
skal/quant-neon

Conversation

@skal65535

@skal65535 skal65535 commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Optimizes QuantizeBlockNEON in src/quantize.cc for ARM/NEON architectures and shares streamlined zigzag emission with SSE2.

Key Changes

• 2x Loop Unrolling: Process 16 coefficients per iteration in the NEON quantization loop, combining dual 8-lane bit weights (weights0 and weights1) into a single 16-bit lane reduction (vaddvq_u16(vorrq_u16(nz0, nz1))), halving vector-to-scalar reduction stalls from 8 to 4 per block.
• Factorized 8-Lane Helper: Factorize vector math with an inline lambda to eliminate code duplication across the unrolled loop.
• Unified EmitRunLevels: Extracted shared helper for both SSE2 and NEON to unify zigzag bitmask remapping, eliminate redundant dc / out->idx_ writes, and share fast exit logic across architectures.
• Empty AC Fast Exit: Blocks with no non-zero AC coefficients (nzn & ~1ull == 0) return immediately without entering the serialization loops.
• Streamlined Zigzag Loop: Pre-compute levels[i] during the zigzag bitmask generation loop, eliminating kZigzag[i] lookups, CalcLog2, bitmasking, and stack array reads from the final serialization loop.

Performance Gains (on Apple Silicon ARM64, 45,000 blocks)

• $q=50$: 0.64 ms $\to$ 0.59 ms (+7.4%, 1.08x faster)
• $q=75$: 0.78 ms $\to$ 0.74 ms (+5.2%, 1.05x faster)
• $q=85$: 1.03 ms $\to$ 0.95 ms (+7.3%, 1.08x faster)
• $q=95$: 2.00 ms $\to$ 1.86 ms (+6.7%, 1.07x faster)

Bit-Exactness

100% bit-exact match across all test fixtures, qualities, and the full CLIC image corpus. All unit tests pass.

@skal65535
skal65535 requested a review from jzern September 19, 2026 04:45
@skal65535 skal65535 self-assigned this Sep 19, 2026
@skal65535
skal65535 force-pushed the skal/quant-neon branch 3 times, most recently from 93e0121 to df301b4 Compare September 19, 2026 06:03
@skal65535
skal65535 marked this pull request as ready for review September 19, 2026 06:04
…d zigzag loop

- Unroll NEON quantization loop by 2 (16 coeffs per iteration), combining
  weights and reducing vector-to-scalar vaddvq reductions from 8 to 4.
- Factorize 8-lane quantization with an inline helper for clean code structure.
- Extract shared EmitRunLevels helper for both SSE2 and NEON.
- Fast exit when ac_mask == 0 for all-zero AC blocks.
- Compute and store level symbols directly in natural order during zigzag
  bitmask generation, eliminating kZigzag lookup, CalcLog2, bitmasking,
  and stack array reads from the serialization loop.
- 100% bit-exact across all test fixtures and qualities (+9% to +23% faster).
Comment thread src/quantize.cc
@skal65535
skal65535 merged commit 5b15007 into main Sep 21, 2026
13 checks passed
@skal65535
skal65535 deleted the skal/quant-neon branch September 21, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants