Use AVX512_VPOPCNTDQ for the population-count kernels - #558
Merged
Conversation
The AVX2 kernels build a population count out of a VPSHUFB nibble lookup
plus VPSADBW and handle 256 bits per iteration. AVX512_VPOPCNTDQ provides
VPOPCNTQ, which counts all eight 64-bit lanes of a ZMM register in one
instruction, so the new kernels handle 2048 bits per iteration with four
accumulators to keep the adds off a single dependency chain.
One 8 KB container on a Xeon Gold 6548N:
popcntSlice 179.9 ns -> 44.7 ns (4.02x vs AVX2)
popcntAndSlice 225.9 ns -> 68.5 ns (3.30x vs AVX2)
popcntOrSlice 226.9 ns -> 68.5 ns (3.31x vs AVX2)
These back GetCardinality, computeCardinality, AndCardinality,
OrCardinality, XorCardinality, Intersects, and the cardinality half of
every bitmap-container boolean operation.
Detection goes through golang.org/x/sys/cpu, so the OSXSAVE and XCR0
opmask/ZMM checks are handled upstream and GODEBUG=cpu.avx512vpopcntdq=off
disables the path at run time. CPUs without VPOPCNTQ keep the AVX2 path.
Claude-Session: https://claude.ai/code/session_0123ePBefqPjrCvhxdwWFakj
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds AVX-512 counterparts to the five AVX2 population-count kernels, selected when the CPU has
AVX512_VPOPCNTDQ.Type of Change
Changes Made
AVX2 has no vector population count, so
popcnt_avx2_amd64.sbuilds one out of a VPSHUFB nibble lookup plus VPSADBW, handling 256 bits per iteration.AVX512_VPOPCNTDQprovidesVPOPCNTQ, which counts all eight 64-bit lanes of a ZMM in a single instruction, so the new kernels handle 2048 bits per iteration: four ZMM loads, fourVPOPCNTQ, four adds, with four accumulators to keep the adds off one dependency chain.The five dispatchers in
popcnt_avx2_amd64.gogain one branch each; no call sites change. CPUs without VPOPCNTQ keep the existing AVX2 path, and non-amd64 and appengine builds are untouched.Detection is
cpu.X86.HasAVX512VPOPCNTDQfromgolang.org/x/sys/cpu, which already verifies that the OS saves the opmask and ZMM state and honorsGODEBUG=cpu.avx512vpopcntdq=offto disable the path at run time. This makesgolang.org/x/sysa direct dependency; it was already in the module graph.Performance Impact
One 8 KB bitmap container (1024 words) on a Xeon Gold 6548N (Emerald Rapids), pinned with
taskset, Go 1.26.3:popcntSlicepopcntAndSlicepopcntOrSliceThese back
GetCardinality,computeCardinality,AndCardinality,OrCardinality,XorCardinality,Intersects, and the cardinality half of every bitmap-container boolean operation.Testing
go test ./...,roaring64, the smat corpus and smat-hit checks,gofmt,go vet, and cross-builds for 386/arm/arm64 and-tags appengine, all on VPOPCNTQ hardware so the new path actually executes.TestPopcntAVX512MatchesGocompares all five kernels against the portable implementations at lengths 0,1,2,3,4,5,7,8,15,16,17,31,32,33,63,64,65,1023,1024,1025 - covering the empty case, the sub-block cases, exact multiples of the 32-word main loop, and the scalar tail.TestPopcntDispatchMatchesGochecks the dispatchers themselves on any CPU.Breaking Changes
None.
Additional Notes
Part of a series applying AVX-512 to roaring, following CRoaring's kernels. It overlaps with #557 and the follow-ups only in
go.mod/go.sum(all add the samegolang.org/x/sysrequirement); the code is disjoint. Worth deciding as a group whether these should share one AVX-512 feature gate rather than one flag per feature - CRoaring gates on VBMI2 + VPOPCNTDQ + BITALG together.https://claude.ai/code/session_0123ePBefqPjrCvhxdwWFakj