Nic*_*ock 13 simd compiler-optimization rust avx2
当我尝试在AVX2 256位向量中存储和加载 256位时,我在发布模式下没有收到预期的输出.
use std::arch::x86_64::*;
fn main() {
let key = [1u64, 2, 3, 4];
let avxreg = unsafe { _mm256_load_si256(key.as_ptr() as *const __m256i) };
let mut back_key = [0u64; 4];
unsafe { _mm256_storeu_si256(back_key.as_mut_ptr() as *mut __m256i, avxreg) };
println!("back_key: {:?}", back_key);
}
Run Code Online (Sandbox Code Playgroud)
在调试模式下:
back_key: [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
在发布模式下:
back_key: [1, 2, 0, 0]
Run Code Online (Sandbox Code Playgroud)
后半部分没有被加载或存储,我无法弄清楚哪一个.
什么是奇怪的是针对本机CPU工作.在发布模式+RUSTFLAGS="-C target-cpu=native"
back_key: [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
我甚至试图通过强制对齐无法获得Clippy错误(我不确定下面的代码是否被认为更正确).
use std::arch::x86_64::*;
#[repr(align(256))]
#[derive(Debug)]
struct Key([u64; 4]);
fn main() {
let key = Key([1u64, 2, 3, 4]);
let avxreg = unsafe { _mm256_load_si256(&key as *const _ as *const __m256i) };
let mut back_key = Key([0u64; 4]);
unsafe { _mm256_storeu_si256((&mut back_key) as *mut _ as *mut __m256i, avxreg) };
println!("back_key: {:?}", back_key);
}
Run Code Online (Sandbox Code Playgroud)
在更彻底地阅读文档之后,很明显我必须将主体提取到另一个函数中,并通过使用注释强制该函数使用 AVX2 进行编译
#[target_feature(enable = "avx2")]
Run Code Online (Sandbox Code Playgroud)
或者编译整个程序
RUSTFLAGS="-C target-feature=+avx2" cargo run --release
Run Code Online (Sandbox Code Playgroud)
第一个选项更好,因为它保证函数中使用的 SIMD 指令被正确编译,调用者只需在调用is_x86_feature_detected!("avx2"). 所有这些都已记录在案,但如果编译器可以警告“嘿,这个函数使用 AVX2 指令,但没有注释,并且#[target_feature(enable = "avx2")]程序不是在全局启用 AVX2 的情况下编译的,所以调用这个函数是未定义的行为”,那就太神奇了。这会让我省去很多头痛!
由于依赖未定义的行为是不好的,我们在操场上的初始程序应该写成:
use std::arch::x86_64::*;
fn main() {
unsafe { run() }
}
#[target_feature(enable = "avx2")]
unsafe fn run() {
let key = [1u64, 2, 3, 4];
let avxreg = _mm256_load_si256(key.as_ptr() as *const __m256i);
let mut back_key = [0u64; 4];
_mm256_storeu_si256(back_key.as_mut_ptr() as *mut __m256i, avxreg);
println!("back_key: {:?}", back_key);
}
Run Code Online (Sandbox Code Playgroud)
一些注意事项:
main不可能不安全,因此不能用 注释target_feature,因此需要提取到另一个函数中x86_64运行代码的 CPU 有avx能力,所以请确保在调用之前进行检查