Skip to content

raid: save xmm instead of ymm on win64, add vzeroupper before returns in AVX kernels - #468

Open
mcimerman wants to merge 3 commits into
intel:masterfrom
mcimerman:raid-vzeroupper
Open

mcimerman wants to merge 3 commits into
intel:masterfrom
mcimerman:raid-vzeroupper

Conversation

@mcimerman

Copy link
Copy Markdown
Contributor

Commit 1

The first commit saves just the low 128 bits of registers, as allowed by the win64 calling convention, and as other kernels do.

Commit 2

The second commit adds vzeroupper before returning from AVX kernels, just as GFNI kernels in erasure_code do it. Did not add it in pq_gen_avx.asm, as that code only uses the xmm part of the registers. It helps everything older than Skylake dodge the AVX<->SSE transition penalty (measured about 40-60 cycles per call on Haswell-EP and about 190 cycles per call on Sandy Bridge, two transitions per call), and is even more important on Skylake. On Skylake, with the high half of the registers dirty, each non-VEX encoded instruction depends on the previous value of its destination register, so instructions that could run in parallel run one after another: personally measured around 5x slowdown for 16 independent sqrtpd on Skylake-SP. The vzeroupper might hurt only on Knights Landing, which I don't have access to anymore unfortunately. [1,2,3]

No negative measurable performance impact on Haswell-EP, Sandy Bridge and Skylake-SP, besides a corner case that Commit 3 mostly takes care of (see below). If needed, I can further test on Comet Lake, and Zen 2.

Commit 3

In xor_gen_avx and xor_gen_avx512, calls whose length is not a multiple of 128 bytes finish the remainder 8 bytes at a time in loop8_bytes, which sits after return_pass. The vzeroupper added in commit 2 shifts that loop by 3 bytes, which costs short calls that run only this loop: on Haswell-EP, raid_funcs_perf -t xor_gen --sources 4 --sizes 64 --csv is 5.1% slower with commits 1-2 than on master. A build with a 3 byte NOP in place of vzeroupper is just as slow per call, so it is the loop's position, not the instruction. Commit 3 aligns loop8_bytes to 16 bytes in xor_gen_avx and xor_gen_avx512, which makes these calls faster than on master on Sandy Bridge, Haswell-EP and Skylake-SP. Lengths that are multiples of 128 bytes don't use this loop and are unaffected.

raid_funcs_perf -t xor_gen --sources 4 --sizes 64 --csv, 8 interleaved rounds ("commits 1-2" is this PR without commit 3, "master + commit 3" is master with only the align 16):

Haswell-EP (Xeon E5-2699 v3, xor_gen_avx)
build median MB/s vs master per round
master 15056.0
commits 1-2 14318.2 -5.1% -5.8% to -1.1%, slower than master in all 8 rounds
master + commit 3 15490.4 +3.1% +1.7% to +5.5%, faster than master in all 8 rounds
this PR (commits 1-3) 15369.2 +2.5% +0.4% to +6.0%, faster than master in all 8 rounds
Skylake-SP (Xeon Gold 6130, xor_gen_avx512)
build median MB/s vs master per round
master 11934.5
commits 1-2 10893.9 -8.7% -8.8% to -8.6%, slower than master in all 8 rounds
master + commit 3 14513.0 +21.6% +21.2% to +22.1%, faster than master in all 8 rounds
this PR (commits 1-3) 14147.5 +18.6% +18.1% to +18.6%, faster than master in all 8 rounds

On Sandy Bridge (Core i5-2520M, xor_gen_avx), the same command gives -7.6% for commits 1-2, +11.0% for master + commit 3 and +11.3% for this PR against master.

The only measurable cost of vzeroupper itself shows in these very short calls, where it is noticeable: comparing master + commit 3 with this PR, about 2.5% on Skylake-SP, within noise on Haswell-EP and Sandy Bridge.

In pq_gen_avx2 and xor_gen_avx, save just the low 128 bits of the
registers, as the Windows x64 calling convention requires only those to
be saved.

Signed-off-by: Miroslav Cimerman <mcimerman@protonmail.com>
Avoids the AVX-SSE transition penalty.

Signed-off-by: Miroslav Cimerman <mcimerman@protonmail.com>
The vzeroupper added before shifts the loop8_bytes by 3 bytes, which
performs worse: raid_funcs_perf -t xor_gen --sources 4 --sizes 64
became 7.6% slower on Sandy Bridge, 5.1% slower on Haswell-EP and
8.7% slower on Skylake-SP. With the loop aligned, the same command
is 11.3%, 2.5% and 18.6% faster than master on these CPUs.

Signed-off-by: Miroslav Cimerman <mcimerman@protonmail.com>
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