linux/lib/crc
Eric Biggers 118da22eb6 lib/crc: x86/crc32c: Enable VPCLMULQDQ optimization where beneficial
Improve crc32c() performance on lengths >= 512 bytes by using
crc32_lsb_vpclmul_avx512() instead of crc32c_x86_3way(), when the CPU
supports VPCLMULQDQ and has a "good" implementation of AVX-512.  For now
that means AMD Zen 4 and later, and Intel Sapphire Rapids and later.
Pass crc32_lsb_vpclmul_avx512() the table of constants needed to make it
use the CRC-32C polynomial.

Rationale: VPCLMULQDQ performance has improved on newer CPUs, making
crc32_lsb_vpclmul_avx512() faster than crc32c_x86_3way(), even though
crc32_lsb_vpclmul_avx512() is designed for generic 32-bit CRCs and does
not utilize x86_64's dedicated CRC-32C instructions.

Performance results for len=4096 using crc_kunit:

    CPU                        Before (MB/s)     After (MB/s)
    ======================     =============     ============
    AMD Zen 4 (Genoa)                  19868            28618
    AMD Zen 5 (Ryzen AI 9 365)         24080            46940
    AMD Zen 5 (Turin)                  29566            58468
    Intel Sapphire Rapids              22340            73794
    Intel Emerald Rapids               24696            78666

Performance results for len=512 using crc_kunit:

    CPU                        Before (MB/s)     After (MB/s)
    ======================     =============     ============
    AMD Zen 4 (Genoa)                   7251             7758
    AMD Zen 5 (Ryzen AI 9 365)         17481            19135
    AMD Zen 5 (Turin)                  21332            25424
    Intel Sapphire Rapids              18886            29312
    Intel Emerald Rapids               19675            29045

That being said, in the above benchmarks the ZMM registers are "warm",
so they don't quite tell the whole story.  While significantly improved
from older Intel CPUs, Intel still has ~2000 ns of ZMM warm-up time
where 512-bit instructions execute 4 times more slowly than they
normally do.  In contrast, AMD does better and has virtually zero ZMM
warm-up time (at most ~60 ns).  Thus, while this change is always
beneficial on AMD, strictly speaking there are cases in which it is not
beneficial on Intel, e.g. a small number of 512-byte messages with
"cold" ZMM registers.  But typically, it is beneficial even on Intel.

Note that on AMD Zen 3--5, crc32c() performance could be further
improved with implementations that interleave crc32q and VPCLMULQDQ
instructions.  Unfortunately, it appears that a different such
implementation would be optimal on *each* of these microarchitectures.
Such improvements are left for future work.  This commit just improves
the way that we choose the implementations we already have.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250719224938.126512-3-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
2025-07-20 20:52:34 -07:00
..
arm lib/crc: arm: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
arm64 lib/crc: arm64: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
loongarch lib/crc: loongarch: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
mips lib/crc: mips: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
powerpc lib/crc: powerpc: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
riscv lib/crc: riscv: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
s390 lib/crc: s390: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
sparc lib/crc: sparc: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00
tests
x86 lib/crc: x86/crc32c: Enable VPCLMULQDQ optimization where beneficial 2025-07-20 20:52:34 -07:00
.gitignore
crc-ccitt.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc-itu-t.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc-t10dif-main.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc4.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc7.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc8.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc16.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc32-main.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
crc64-main.c lib/crc: Explicitly include <linux/export.h> 2025-06-30 09:31:57 -07:00
gen_crc32table.c
gen_crc64table.c
Kconfig lib/crc: Remove ARCH_HAS_* kconfig symbols 2025-06-30 09:31:57 -07:00
Makefile lib/crc: x86: Migrate optimized CRC code into lib/crc/ 2025-06-30 09:31:57 -07:00