Skip to content

Use AVX2 for dense in-place XOR - #550

Closed
perfloop-agent wants to merge 1 commit into
RoaringBitmap:masterfrom
perfloop-oss:perfloop-pr-open-je71hpbx27
Closed

perfloop-agent wants to merge 1 commit into
RoaringBitmap:masterfrom
perfloop-oss:perfloop-pr-open-je71hpbx27

Conversation

@perfloop-agent

@perfloop-agent perfloop-agent commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Description

This adds an AVX2 fallback for dense bitmap XOR stores on amd64. The existing AVX-512 path remains first, and portable builds keep their scalar implementation.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Performance improvement
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Test improvements
  • Build/CI changes

Changes Made

What was changed?

  • Added a four-vector AVX2 XOR-and-store routine with vector and scalar tails.
  • Added aliasing and dispatch tests for empty, tail, and full bitmap lengths.

Why was it changed?

  • The dense XOR path fell back to a scalar word loop when AVX-512 was unavailable, even on CPUs with AVX2.
  • This path rewrites the already-counted bitmap words and is on both in-place and out-of-place dense XOR operations.

How was it changed?

  • xorSlice selects AVX-512, then AVX2, then the existing portable loop.
  • The AVX2 routine loads each source block before storing it, so the destination may alias either source. The cardinality pass, representation threshold, and copy-on-write boundary are unchanged.

Testing

  • go test ./...
  • go test -tags=appengine
  • GOARCH=arm64 go build .
  • GOARCH=386 go build .
  • Formatting and go tool unconvert ./...

Checks: 5 passed.

Formatting

The changed Go files are gofmt-formatted.

Fuzzing

Not run. This change does not touch serialization or fuzzing code.

Performance Impact

On amd64 CPUs without the AVX-512 bitmap-operations path, dense XOR uses AVX2 vector stores instead of the portable word loop. AVX-512, non-amd64, appengine, and non-AVX2 paths are unchanged, with no new allocation or public API.

Workload: Bitmap.Xor on 50 dense matching containers with AVX-512 disabled

Metric Before After Change
ns/op 45113 20500 54.6% lower

Running Benchmarks

BenchmarkXorDense covers the in-place dense path, and BenchmarkDenseBitmapOps/Xor covers the shared out-of-place path. Both fallback measurements disable AVX-512 so the AVX2 selection is exercised.

Performance Analysis

The implementation is limited to the existing plain XOR backend. It preserves the low-cardinality array conversion and the existing architecture fallbacks.

Breaking Changes

None.

Related Issues

N/A

Additional Notes

None.


Generated by Perfloop. Human sponsor: Tomás Senart. Measurements and checks.

Signed-off-by: Tomás Senart <ts@perfloop.ai>
@perfloop
perfloop Bot force-pushed the perfloop-pr-open-je71hpbx27 branch from 25b8646 to ed00e0a Compare November 8, 2026 01:24
@perfloop-agent

Copy link
Copy Markdown
Contributor Author

Closing this pull request. On the repository's real datasets the dense XOR path is reached, but the most this change could save is about 3% of the operation, which is inside the run-to-run noise we measured (about ±12%). That does not justify the extra code. Thank you for your time.

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.

1 participant