Hi,

Thanks for working on this. I've tried to speed up decoding in the
past, and didn't get any improvement at all really.

I currently have very little time (if any) to review anything, as
might be apparent from the recent PRs on GitHub. So, it might be a
while before this is merged. Anyway, have you used the FLAC decoding
testbench to verify decoding of edge cases? See
https://xiph.org/flac/2022/09/08/decoder-testbench.html

Kind regards, Martijn van Beurden

Op do 22 okt 2026 om 16:22 schreef olivier tristan <[email protected]>:
>
> Hi all,
>
> I work at UVI, where we make virtual instruments and sample libraries.
> Our libraries ship their samples as FLAC, and the sampler streams them
> from disk while you play.
>
> Every note that is not already in the cache starts a stream that decodes
> FLAC frames on a worker thread. With a lot of voices, decoding is a
> noticeable part of the CPU load, so I spent some time profiling libFLAC
> on our material.
>
> The result is a series of 7 patches against current master:
>
>    https://github.com/UVI-Dev/flac-fork/commits/decode-speedups
>
> Decoding is 36 to 44% faster on Apple M1 and 21 to 43% faster on x86-64,
> depending on compiler and material, with bit-identical output. I
> measured every commit on its own on both platforms and only kept changes
> that are not slower anywhere. Each commit message has its numbers.
>
> In short:
>
> 1. Rice parameter 0 partitions go through the fast block reader instead
> of one read_unary call per residual. Helps quiet passages (decay tails,
> which our samples have plenty of), no change on dense music.
> 2. The stop bit and the LSBs are dropped from the bit buffer with one
> shift instead of two. The buffer goes from one residual to the next
> through that chain, so one operation less there shows.
> 3. undo_channel_coding() tests side_subframe_in_use once per frame
> instead of once per sample, so the side-coded loops vectorize with MSVC
> and clang-cl (clang on macOS already managed).
> 4. The "decoded sample fits bps" check no longer exits early, so it
> vectorizes too.
> 5. LPC and fixed subframes are restored while the residual is read,
> instead of decoding the residual first and running lpc_restore_signal()
> in a second pass.
> 6. Frame CRC-16 with PMULL folding on arm64.
> 7. Frame CRC-16 with PCLMULQDQ on x86-64, chosen at run time.
>
> Patch 5 is where most of the gain is. The rice decoding is bound by the
> bit position, the restore by the previous samples, and in one loop the
> two chains overlap. We got the idea from dr_flac, which does this.
> Residuals are still stored for the client.
>
> For orders up to 12 the loop is instantiated per order, and the
> prediction of the next sample but its newest tap is computed while the
> current sample is restored. That way the sample to sample dependency is
> one multiply-add, the shift and the add, whatever the compiler does with
> the additions.
>
> The newest sample is kept in a variable, but the 11 older ones only
> where there are enough registers. On x86 a window of 12 does not fit,
> both MSVC and clang spill it and shift it in memory for every sample, so
> there the older samples are read back from the output buffer. On arm64
> reading them back costs up to 5%.
>
> So bitreader.c picks the window with FLAC__CPU_X86_64 / FLAC__CPU_IA32:
> x86 reads the older samples back from the buffer, other architectures
> keep all 12 in variables. It comes down to the number of registers, and
> each choice measured best on its own side.
>
> About 6 and 7: the table CRC-16 was 10 to 20% of the decoding time. We
> first considered an option to skip it for frames that follow a valid
> one, but computing it faster keeps every frame checked and now costs
> almost nothing, so there is no such option in this series.
>
> Numbers (ns per sample, all channels, full decode from memory, best of 8
> runs, CRC checked):
>
>                              master   series   change
>    Apple M1, clang 15
>      16-bit samples            5.65     3.18   -43.7%
>      24-bit samples            6.86     3.91   -43.1%
>      16-bit music              7.01     4.47   -36.2%
>
>    Core Ultra 9 185H, MSVC 19.29
>      16-bit samples            6.69     4.58   -31.6%
>      24-bit samples            9.39     5.49   -41.6%
>      16-bit music              7.83     5.75   -26.5%
>
>    Core Ultra 9 185H, clang-cl 23
>      16-bit samples            5.76     4.02   -30.2%
>      24-bit samples            7.08     5.12   -27.7%
>      16-bit music              6.52     5.18   -20.6%
>
>    Core Ultra 9 185H, MSVC 19.51 (VS 2026)
>      16-bit samples            7.66     4.45   -41.8%
>      24-bit samples            7.91     5.58   -29.4%
>      16-bit music              9.57     5.42   -43.4%
>
> With MSVC 19.51, master itself is slower than with 19.29 on 16-bit
> samples and music (and faster on 24-bit), while the series runs at the
> same speed with both. Better compare the absolute numbers there.
>
> Testing: the whole test suite passes (ctest, including the streams test)
> on macOS arm64, and the decoded output is identical to master for every
> commit on all the sets above. flac -t passes on all the test files on
> Windows. The PCLMULQDQ CRC was also checked against a bitwise CRC-16 on
> random data.
>
> Every commit builds on its own without new warnings with clang -Wall
> -Wextra, and the final state has no new warning with MSVC 19.29 (default
> and /W4) and 19.51.
>
> Things I would like your opinion on:
>
> - bitreader.c now knows about LPC prediction (it includes lpc.h), and
> the per-order instantiation leans on macros around the deduplicated rice
> reader. I tried to keep it close to how the BMI2 variant is done, but
> there may be a layout you prefer.
> - I have only tested arm64 macOS and x86-64 Windows. Linux/GCC results
> would be welcome.
>
> I can split this into separate pull requests if that is easier to
> review, starting with 1 to 4 which are small.
>
> Thanks,
>
> --
> Olivier Tristan
> Research & Development
> www.uvi.net
>
> _______________________________________________
> flac-dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
_______________________________________________
flac-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to