这个问题在这里已经有了答案:
SIMD code works in Debug, but does not in Release
(1 个回答)
2年前关闭。
当我尝试 store 和 load 256 位与 AVX2 256 位向量之间的往来时,我在 Release模式下没有收到预期的输出。
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);
}
playground
在 Debug模式下:
back_key: [1, 2, 3, 4]
在 Release模式下:
back_key: [1, 2, 0, 0]
后半部分没有被加载或存储,我无法弄清楚是哪个。
奇怪的是针对 native CPU 工作。在 Release模式下 +
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);
}
最佳答案
在更彻底的 reading the docs 之后,很明显我必须将主体提取到另一个函数中,并通过注释来强制使用 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
功能,因此请确保在调用 关于rust - 为什么在调试和 Release模式下存储和加载 AVX2 256 位向量会产生不同的结果?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52433389/