Skip to content

Optimize SIMD pipelines and math across compression/decompression paths - #665

Open
GermanAizek wants to merge 1 commit into
ARM-software:mainfrom
GermanAizek:main
Open

Optimize SIMD pipelines and math across compression/decompression paths#665
GermanAizek wants to merge 1 commit into
ARM-software:mainfrom
GermanAizek:main

Conversation

@GermanAizek

Copy link
Copy Markdown
Contributor

@solidpixel
Thank you so much for your support and for developing ASTC encoder. I would like to help and contribute; I already contributed to this project about 5 years ago. According to the tests, we managed to optimize absolutely all bench indicators, even though fastest preset dropped slightly

The tests were conducted using your benchmarks. The testing was performed on a Xeon 2xE5-2699v3 (18+18 - 36+36 threads) cpu with max AVX2 support

description commit changes:

  • Decompress: Refactor lerp_color_int formula to halve vector multiplications.
  • Decompress: Hoist endpoint offsets and diffs outside the texel loop in compute_symbolic_block_difference_1plane_1partition.
  • Endpoints: Add fast path for unit_weights in compute_error_squared_rgb_single_partition (eliminates 12 vector muls/iter).
  • Averages/Dirs: Eliminate redundant register shuffles/switches in projection calculations.
  • Weights: Add constant_wes fast paths in compute_error_of_weight_set_1plane/2planes to bypass redundant vector loads and muls.
  • Weight Align: Simplify weight_down/weight_up arithmetic in realign_weights_decimated.
  • Weight Align: Break ILP dependency chains in compute_lowest_and_highest_weight for cut errors.
image image image image image

@ARM-software ARM-software deleted a comment from Dreamer1 Aug 27, 2026
@solidpixel

Copy link
Copy Markdown
Contributor

Awesome, thanks - will take a look.

@GermanAizek

Copy link
Copy Markdown
Contributor Author

Awesome, thanks - will take a look.

It’s very strange, but locally my CTest runs successfully, while it doesn’t through GitHub Actions — how is that possible?

@solidpixel

Copy link
Copy Markdown
Contributor

Looks like it needs updated reference CSV files.

@solidpixel

solidpixel commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

What compiler and build settings are you using?

I get a significant performance regression (15-20%) compared to the main branch when compiling for AVX2 with Clang++-20 (only tested on an older CoffeeLake Core-i5 so far).

I also get a small IQ drop on some images.


vmask4 tdm0 = texel_datum.swz<0,0,0,0>() > zero;
sum_xp += select(zero, texel_datum, tdm0);
if (dr > 0.0f)

@solidpixel solidpixel Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect all the changes to use branches to be a significant regression unless the compiler turns it back into a select - these branches are inherrently unpredictable, and the cost of the mispredict far outweighs the cost of the additional instructions when vectorized.

@solidpixel solidpixel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Biggest issue currently is that I can't reproduce the improvements - on my test hardware I get a large regression. I don't have a Xeon to hand at the moment - can test more in the office next week. Tested the AVX2 build on:

  • Intel Core i5-9600K (desktop part)
  • Intel Core Ultra 7 165U (mobile part)

If I revert all of the changes in astcenc_averages_and_directions.cpp I avoid the regression, but still don't see any improvement over the current main branch.

if (!constant_wes)
{
weight_error_scale = gatherf_byte_inds<vfloat>(ei.weight_error_scale, texel);
vfloat wes = gatherf_byte_inds<vfloat>(ei.weight_error_scale, texel);

@solidpixel solidpixel Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is invalid I think. It's only safe if weight_error_scale is guaranteed to be 1.0f in the cases where it's flagged as constant, but it's not guaranteed to be (I don't think). You need to keep the multiply outside of the if.

Ditto later change too.

@GermanAizek

GermanAizek commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

What compiler and build settings are you using?

I get a significant performance regression (15-20%) compared to the main branch when compiling for AVX2 with Clang++-20 (only tested on an older CoffeeLake Core-i5 so far).

I also get a small IQ drop on some images.

Sorry for the long answer.

Yes, indeed, I didn’t mention the Linux kernel version and the compiler.

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-linux-gnu/16/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 16.2.0-1' --with-bugurl=file:///usr/share/doc/gcc-16/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2,rust,cobol,algol68 --prefix=/usr --with-gcc-major-version-only --program-suffix=-16 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/reproducible-path/gcc-16-16.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/reproducible-path/gcc-16-16.2.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=3
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 16.2.0 (Debian 16.2.0-1) 
$ uname
Linux
$ uname -r                                                                                                                                                                                                                                                      
7.1.10+deb14-amd64

@GermanAizek

Copy link
Copy Markdown
Contributor Author

when compiling for AVX2 with Clang++-20

I did the wrong thing; it would have been better to test performance changes directly on GCC and Clang and display the data about them together. Perhaps -O optimization flags work differently in Clang.

@solidpixel

solidpixel commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Perhaps -O optimization flags work differently in Clang.

I've not checked for a few years but when I last checked Clang was about 10-15% faster than GCC, and about 30% faster than MSVC. Using MSVC with clang-cl was somewhere between native Clang and GCC.

@GermanAizek

Copy link
Copy Markdown
Contributor Author

@solidpixel I suggest temporarily abandoning these changes. I need to take into account working with two compilers at once and the maximum -O3 compiler flags. Later, I will send you more guaranteed changes for the PR if there is an improvement with both compilers.

@GermanAizek

GermanAizek commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

Perhaps -O optimization flags work differently in Clang.

I've not checked for a few years but when I last checked Clang was about 10-15% faster than GCC, and about 30% faster than MSVC. Using MSVC with clang-cl was somewhere between native Clang and GCC.

I am continuing the development of the TCC compiler (https://en.wikipedia.org/wiki/Tiny_C_Compiler - Fabrice Bellard) (https://github.com/GermanAizek/tinycpp) and I can say that Clang is not always more efficient than GCC. I have automated benchmarks that compare examples using GCC, Clang, and TCC.

@GermanAizek

Copy link
Copy Markdown
Contributor Author

@solidpixel

Copy link
Copy Markdown
Contributor

I can say that Clang is not always more efficient than GCC.

For sure, I was only talking in the context of astcenc, and I last checked properly with GCC 11 or so, it's been a while. I know GCC historically had some efficiency problems with intrinsics, and it has been getting better in recent years. I really should do another sweep with latest compilers.

@GermanAizek

GermanAizek commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@solidpixel If you’re interested, I can send you a report with benchmark GCC vs Clang vs TCC data, but on average, Clang is 5–10 % faster than GCC, yet it consumes significantly more use RAM and size in compiled binary file due to unrolling and an excess of inline functions.

- Split partition averages, error squaring, and endpoint evaluation loops into unmasked SIMD fast paths and tails
- Simplify ideal weight decimation by eliminating redundant error scale multiplies when constant
- Hoist dot products and simplify weight difference calculations in weight realignment and ideal color finding
- Hoist quantization table lookups in color quantization
- Enable BMI/BMI2/LZCNT instructions for AVX2 builds
@GermanAizek

GermanAizek commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@solidpixel I force push new commit e40f9c1

At the moment, I have an increase in MT/s across two compilers GCC and Clang.

If there is indeed an increase with your microarchitecture, I’ll create graphs for the PR (I have 2xE5-2699v3, 22 cores and 72 threads on Haswell).

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