Skip to content

Clear upper vector registers after the LtHash AVX-512 kernels - #4164

Merged
masih merged 2 commits into
mainfrom
masih/1789405586-lthash-vzeroupper
Sep 14, 2026
Merged

masih merged 2 commits into
mainfrom
masih/1789405586-lthash-vzeroupper

Conversation

@masih

@masih masih commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #4151. The Go compiler emits no VZEROUPPER after archsimd AVX-512 code, so the LtHash SIMD kernels returned to their callers with dirty upper ZMM halves. Any legacy-SSE code that runs next (memmove, SHA-NI, encoding helpers) then pays an upper-state merge penalty until the registers are cleared; a throwaway benchmark of Expand followed by sha256.Sum256 over the 2 KiB serialisation goes 4.36 µs → 3.69 µs (-15%) on an Intel Xeon 8559C once the guard is in place, while the package's own benchmarks are neutral (MixIn +~1 ns, the cost of the instruction itself).

This adds a package-local vzeroupper() asm stub, the same shape as the one in #4157, and calls it from thin wrappers registered in simdBackend(), the one place every SIMD entry point passes through, so a kernel added later cannot skip it. Hash output is unchanged and the differential tests pass under both builds; the stub is only built under goexperiment.simd && amd64.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@masih
masih marked this pull request as ready for review September 14, 2026 17:12
@cursor

cursor Bot commented Sep 14, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Performance-only guard around existing SIMD paths; no change to hash semantics, gated to simd amd64 builds.

Overview
Adds a goexperiment.simd && amd64 assembly stub that executes VZEROUPPER, and wires the LtHash AVX-512 backend so expand, add, and sub always call it after the SIMD kernels return.

This fixes dirty upper ZMM state left behind when the compiler does not clear registers after AVX-512, which was slowing subsequent legacy-SSE work in callers (e.g. memmove, SHA-NI). Hash results are unchanged; the extra instruction is only on the SIMD backend handoff path.

Reviewed by Cursor Bugbot for commit 52b4651. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedSep 14, 2026, 5:19 PM

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown

LtHash default vs SIMD (uci-default)

CPU: AMD EPYC 7R13 Processor

This runner CPU lacks AVX-512F + VBMI2, so only the default backend ran.

goos: linux
goarch: amd64
pkg: github.com/sei-protocol/sei-chain/sei-db/state_db/sc/flatkv/lthash
cpu: AMD EPYC 7R13 Processor
             │   default    │
             │    sec/op    │
Expand-16      2.800µ ±  3%
MixIn-16       419.1n ±  9%
MixOut-16      435.9n ±  5%
HashKV-16      3.518µ ± 10%
HashChunk-16   7.639m ±  7%
geomean        6.724µ

          │   default    │
          │     B/s      │
Expand-16   697.5Mi ± 6%

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown

LtHash default vs SIMD (ubuntu-latest)

CPU: AMD EPYC 7763 64-Core Processor

This runner CPU lacks AVX-512F + VBMI2, so only the default backend ran.

goos: linux
goarch: amd64
pkg: github.com/sei-protocol/sei-chain/sei-db/state_db/sc/flatkv/lthash
cpu: AMD EPYC 7763 64-Core Processor                
            │   default   │
            │   sec/op    │
Expand-4      3.217µ ± 1%
MixIn-4       384.6n ± 1%
MixOut-4      384.2n ± 0%
HashKV-4      3.565µ ± 1%
HashChunk-4   7.335m ± 1%
geomean       6.590µ

         │   default    │
         │     B/s      │
Expand-4   607.1Mi ± 1%

@seidroid seidroid Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Adds a package-local vzeroupper() asm stub and calls it at the three SIMD→scalar handoff points in the LtHash AVX-512 backend. The change is correct: the stub is gated behind goexperiment.simd && amd64, is only reachable via simdBackend() (which requires AVX-512F+VBMI2, so the VEX-encoded instruction can never fault), the hash output is unaffected, and the len(data) > blake3ChunkLen early return correctly omits the call since no SIMD kernel ran on that path.

Findings: 0 blocking | 1 non-blocking | 0 posted inline

Blockers

  • None at the file/PR level.

Non-blocking

  • [suggestion] The vzeroupper() call is repeated at the tail of each of the three SIMD kernels, so nothing enforces it for a kernel added later — a fourth *SIMD function that forgets the call silently reintroduces the dirty-upper-state penalty this PR removes. simdBackend() is the single point every SIMD entry point is registered through and could wrap the three function values there instead (at the cost of one indirect call), or at minimum a short note on the vzeroupper declaration stating that every SIMD kernel must end with it would make the requirement discoverable. Only the expandSIMD site carries the rationale comment today; the addSIMD/subSIMD calls are bare.

@codecov

codecov Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.59%. Comparing base (33fa177) to head (52b4651).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4164      +/-   ##
==========================================
- Coverage   66.65%   65.59%   -1.07%     
==========================================
  Files        2200     2091     -109     
  Lines      169420   157994   -11426     
==========================================
- Hits       112933   103636    -9297     
+ Misses      56346    54217    -2129     
  Partials      141      141              
Flag Coverage Δ
sei-db 74.50% <ø> (ø)
sei-db-state-db ?
sei-db-state-db-pr 89.49% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 109 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Taken in 52b4651: the vzeroupper() call now lives in wrappers registered in simdBackend(), so every SIMD entry point passes through it and the kernels themselves stay bare. MixIn stays at ~28.5 ns/op with the extra indirect call.

@masih
masih enabled auto-merge September 14, 2026 20:25
@masih
masih added this pull request to the merge queue Sep 14, 2026
Merged via the queue into main with commit 3cad9bf Sep 14, 2026
103 of 105 checks passed
@masih
masih deleted the masih/1789405586-lthash-vzeroupper branch September 14, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants