rust-lang / rust-lang/rust

SEE-AVX-stall when using target-cpu=znver2. Thus ~25 times slower.

Open
#120,108 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-codegen A-LLVM C-optimization I-slow O-x86_64 T-compiler
Dominant language
Rust
Stars
119k
Forks
16.2k
PR merge metrics
PR metrics pending

Description

The performance of the following function is realy slow when i use target-cpu=znver2, my own cpu. Without a target-cpu set it is ~25 times quicker.

fn main() {
    let row = std::hint::black_box(& [125u8; 8]);
    let mut data = [0u32; 8];
    let data = std::hint::black_box(&mut data);

    for _ in 0..500_000_000u64 {
        std::hint::black_box(slow(*row, data));
    }
}
#[inline(never)]
pub fn slow(mut row: [u8; 8], data: &mut [u32; 8]) -> [u8; 8] {
    for data in data {
        *data <<= 5;
    }
    
    row[7] = 0;
    row
}

I have run it twice with perf. Once with the target-cpu set and once without:

$ RUSTFLAGS="-C target-cpu=znver2" perf stat -e "sse_avx_stalls" cargo run --release
   Compiling perf_test v0.1.0 (/home/barfussmann/Documents/perf_test)
    Finished release [optimized + debuginfo] target(s) in 0.20s
     Running `target/release/perf_test`

 Performance counter stats for 'cargo run --release':

    10.486.365.719      sse_avx_stalls:u                                                      
      32,070525175 seconds time elapsed
      31,812318000 seconds user
       0,125145000 seconds sys


$ perf stat -e "sse_avx_stalls" cargo run --release
   Compiling perf_test v0.1.0 (/home/barfussmann/Documents/perf_test)
    Finished release [optimized + debuginfo] target(s) in 0.19s
     Running `target/release/perf_test`

 Performance counter stats for 'cargo run --release':

               344      sse_avx_stalls:u                                                      
       1,321682733 seconds time elapsed
       1,213303000 seconds user
       0,104931000 seconds sys

The culprit seems to be SSE-AVX stalls. When looking at the assembly of the slow function with target-cpu set (Compiler Explorer: https://godbolt.org/z/69TxxzG4T). there is a AVX instruction before the SSE4a instruction "exrtq" an Amd specific instruction. There isn't a zveroupper between both instructions. This should be the causes of the SSE-AVX-stall when I'm not mistaken.


example::slow:
        vmovdqu ymm0, ymmword ptr [rsi]   // AVX
        vmovq   xmm1, rdi                  
        extrq   xmm1, 56, 0               // SSE4a
        vmovq   rax, xmm1
        vpslld  ymm0, ymm0, 5
        vmovdqu ymmword ptr [rsi], ymm0
        vzeroupper
        ret

Meta:
I'm running Fedora:

$ rustc --version --verbose
rustc 1.75.0 (82e1608df 2023-12-21)
binary: rustc
commit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112
commit-date: 2023-12-21
host: x86_64-unknown-linux-gnu
release: 1.75.0
LLVM version: 17.0.6

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided Rust reproducer with and without RUSTFLAGS="-C target-cpu=znver2", then compare the generated assembly shown in the issue and the sse_avx_stalls measurements. Investigate the compiler or LLVM code-generation path responsible for mixing AVX and SSE4a instructions; done means the cause is confirmed and a validated compiler change or regression test addresses the stall.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.