当我尝试store和load 256位往返于AVX2 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);
}
在调试模式下:
back_key: [1, 2, 3, 4]
在释放模式下:
back_key: [1, 2, 0, 0]
后半部没有被加载或存储,我不知道哪一个。
针对本机CPU的工作很奇怪。在释放模式下+ RUSTFLAGS="-C target-cpu=native"
back_key: [1, 2, 3, 4]
我甚至试图通过强制对齐无济于事来摆脱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);
}
答案 0 :(得分:3)
经过更深入的reading the docs处理后,很明显,我必须将主体提取到另一个函数中,并通过用AVX2对其进行注释来迫使该函数使用AVX2进行编译。
#[target_feature(enable = "avx2")]
或使用编译整个程序
RUSTFLAGS="-C target-feature=+avx2" cargo run --release
第一个选项更好,因为它可以保证函数中使用的SIMD指令被正确编译,只是在调用方使用is_x86_feature_detected!("avx2")
之前,调用方要检查其CPU是否具有这些功能。所有这些都已记录在案,但是如果编译器可以警告“嘿,此函数使用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);
}
一些注意事项:
main
不能不安全,因此不能用target_feature
进行注释,因此有必要提取到另一个函数中x86_64
CPU具有avx
功能,因此请确保在调用之前进行检查