Enhance simde/x86/gfni.h - #1429
Conversation
Later commits use these features to compute GF(2^8) operations without large lookup tables.
A GF(2) affine transform with a constant matrix is two 16-entry table lookups, which the compiler computes at compile time. At run time, the transform is two byte shuffles and one XOR.
This removes the run-time XOR with the broadcast affine constant.
…nsform A multiply by a constant in GF(2^8) is a linear map over GF(2). A precomputed table gives the affine matrix for each constant, and the multiply then uses the constant-matrix nibble path. Without byte shuffles, the matrix path is slower than the schoolbook multiply; the code keeps the schoolbook multiply in that condition.
The AES S-box applies an affine transform after the GF(2^8) inverse. The code removes that transform and keeps the inverse.
For a compile-time-constant matrix, the code folds the matrix and the AES correction into two nibble tables. When the matrix is the AES matrix and the constant is 0x63, the operation becomes one SubBytes.
This path is for targets that have byte shuffles but no AES instructions. The tower field turns the GF(2^8) inverse into GF(2^4) operations, which 16-entry shuffle tables solve.
For a compile-time-constant matrix, the code folds the matrix into the tables that map the tower-field inverse back to the standard basis.
This path is for targets that have byte shuffles. The multiply uses the Karatsuba method over GF(2^4) with log and exp tables.
The AES and tower-field paths are faster than the 256-byte lookup table. The table remains only for targets that have no AES and no byte shuffles. The wide inverse functions now use the narrower fallbacks, which include the new paths.
The narrower fallbacks include the constant-operand and tower-field paths. The removed wide-vector implementations did not.
| SIMDE_TEST_GFNI_MUL_CONST(0x00); SIMDE_TEST_GFNI_MUL_CONST(0x01); | ||
| SIMDE_TEST_GFNI_MUL_CONST(0x02); SIMDE_TEST_GFNI_MUL_CONST(0x1b); | ||
| SIMDE_TEST_GFNI_MUL_CONST(0x53); SIMDE_TEST_GFNI_MUL_CONST(0x57); | ||
| SIMDE_TEST_GFNI_MUL_CONST(0x80); SIMDE_TEST_GFNI_MUL_CONST(0xff); |
There was a problem hiding this comment.
warning C4309: 'static_cast': truncation of constant value
https://ci.appveyor.com/project/nemequ/simde/builds/54552506/job/hlmksf28wd24vg2y#L1168
|
Thank you for this PR @fo40225
Do you have timing data to share? Can you explain a bit about your use case and motivation? We love to hear how people are using SIMDe, it is helpful to us! |
SIMDe GFNI old vs new speedup (spd = old ÷ new, >1 = new is faster)With GFNI hardware (rocketlake, alderlake, raptorlake, meteorlake, znver4): Without GFNI hardware (emulated path):
Summary: the new version wins big on constant-operand paths (folded at compile |
|
I am trying to write a faster zlib compression and decompression library based on GFNI instructions (although it haven't succeeded yet). Recent PRs was just a quick fix for issues I ran into while using simde. |
Add AVX2 versions of the tower-field multiply, the inverse, and the fused affine inverse with a constant matrix. One broadcast moves each 16-byte table to the two ymm lanes. The wide multiply, inverse, and affine-inverse operations use these paths when AVX2 is available.
Summary
This change makes the GFNI emulation faster.
The changed files are
simde/x86/gfni.handtest/x86/gfni.c.New feature detection.
The macro
SIMDE_X_GFNI_HAVE_AESdetects hardware AES support.The support comes from AES-NI on x86 or the crypto extension on ARMv8.
The macro
SIMDE_X_GFNI_HAVE_SHUFFLEdetects byte-shuffle support.New AES path.
When the hardware has AES, the function
simde_x_mm_gf2p8inverse_epi8uses the AES S-box to compute the GF(2⁸) inverse.New lookup tables undo the ShiftRows and affine steps of AES.
When the matrix is A_aes and the constant is 0x63, the affineinv operation becomes one SubBytes operation.
New tower-field path.
When the hardware has shuffle but no AES, the code computes the inverse and the multiply in the tower field GF((2⁴)²).
New lookup tables hold the log, exp, square, and basis-change values of GF(2⁴).
The multiply uses the Karatsuba method over GF(2⁴).
New constant-matrix path.
When the matrix is a compile-time constant, the code turns the matrix into two nibble lookup tables.
The affine transform then becomes two shuffles and one XOR at run time.
The new 256-entry table
simde_x_gf2p8_mul_matrix_lutturns a multiply by a GF(2⁸) constant into an affine transform.This path needs the two conditions
SIMDE_CHECK_CONSTANT_andSIMDE_X_GFNI_HAVE_SHUFFLE.Without shuffle, the matrix multiply uses a slower movemask loop.
In that condition, the usual schoolbook multiply is faster.
Thus the code does not use the constant-multiply path without shuffle.
Removed old code.
This change removes the old lookup-table inverse implementations for SSE4.1, AVX2, and AVX512BW; the new methods are faster than a large table lookup.
CPUs that support AVX512 but not GFNI become much slower with 512-bit operations; thus the 512-bit functions now use the 256-bit fallback path.
New tests.
The file
test/x86/gfni.cgets new test functions.