Rust target-cpu=native SIMD 执行速度变慢
Rust target-cpu=native gets slower SIMD execution
我正在对 x86 内在函数的 Rust 包装器进行简单测试:Leibniz 级数对 PI 的近似:
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
fn main() {
let mut n: u64 = 0;
let pi4 = std::f64::consts::PI / 4.0;
unsafe {
let mut dens = _mm256_set_pd(1.0f64, -3.0f64, 5.0f64, -7.0f64);
let adder = _mm256_set_pd(8.0f64, -8.0f64, 8.0f64, -8.0f64);
let ones = _mm256_set1_pd(1.0f64);
let mut rsum = _mm256_set1_pd(0.0f64);
let mut quotients: __m256d;
loop {
quotients = _mm256_div_pd(ones, dens);
rsum = _mm256_add_pd(rsum, quotients);
dens = _mm256_add_pd(dens, adder);
n = n + 1;
let vlow = _mm256_extractf128_pd(rsum, 0);
let vhigh = _mm256_extractf128_pd(rsum, 1);
let add_partial = _mm_add_pd(vlow, vhigh);
let sum = _mm_cvtsd_f64(add_partial)
+ _mm_cvtsd_f64(_mm_unpackhi_pd(add_partial, add_partial));
if f64::abs(pi4 - sum) < 1.0e-9 {
break;
}
}
}
println!("Steps: {}", 4 * n);
}
在功能上,该程序按预期工作。我的 CPU 型号是“AMD A8-9600 RADEON R7”,并且:
$ rustc --target=x86_64-linux-kernel --print target-cpus
Available CPUs for this target:
native - Select the CPU of the current host (currently bdver4).
编译时:
$ cargo build --release
时间是:
$ time target/release/sotest
real 0m1.668s
user 0m1.667s
sys 0m0.001s
但是对于“本地”目标,它运行得更慢:
$ RUSTFLAGS="-C target-cpu=native" cargo build --release
...
$ time target/release/sotest
real 0m2.783s
user 0m2.778s
sys 0m0.004s
问题是“本地”目标有什么问题-cpu?第一眼看到 documentation,我希望二进制文件利用我 CPU 提供的所有扩展:
The compiler will translate this into a list of target features.
即使不考虑扩展,为什么会变慢?
顺便说一句,编译选择 avx 扩展会产生很大的提升:
RUSTFLAGS="-C target-feature=+avx" cargo build --release
...
real 0m0.358s
user 0m0.354s
sys 0m0.004s
编辑:使用 Ubuntu 20.04 内核 5.4.0-72-generic。
rustc 1.51.0
我猜你遇到了这个错误:https://github.com/rust-lang/rust/issues/83027, which was resolved on March 17, 2021 by https://github.com/rust-lang/rust/pullis/83084。
错误是当使用 native
时,target_feature
没有正确应用,这是所有内在函数使用的。因此,您对内部函数的调用可能没有被内联。您应该查看配置文件以确认这一点。
更一般地说,我建议使用运行时 CPU 特征检测和正确使用 #[target_feature]
。您应该只从至少启用了 avx
功能的函数调用对 32 字节向量进行操作的函数。
我正在对 x86 内在函数的 Rust 包装器进行简单测试:Leibniz 级数对 PI 的近似:
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
fn main() {
let mut n: u64 = 0;
let pi4 = std::f64::consts::PI / 4.0;
unsafe {
let mut dens = _mm256_set_pd(1.0f64, -3.0f64, 5.0f64, -7.0f64);
let adder = _mm256_set_pd(8.0f64, -8.0f64, 8.0f64, -8.0f64);
let ones = _mm256_set1_pd(1.0f64);
let mut rsum = _mm256_set1_pd(0.0f64);
let mut quotients: __m256d;
loop {
quotients = _mm256_div_pd(ones, dens);
rsum = _mm256_add_pd(rsum, quotients);
dens = _mm256_add_pd(dens, adder);
n = n + 1;
let vlow = _mm256_extractf128_pd(rsum, 0);
let vhigh = _mm256_extractf128_pd(rsum, 1);
let add_partial = _mm_add_pd(vlow, vhigh);
let sum = _mm_cvtsd_f64(add_partial)
+ _mm_cvtsd_f64(_mm_unpackhi_pd(add_partial, add_partial));
if f64::abs(pi4 - sum) < 1.0e-9 {
break;
}
}
}
println!("Steps: {}", 4 * n);
}
在功能上,该程序按预期工作。我的 CPU 型号是“AMD A8-9600 RADEON R7”,并且:
$ rustc --target=x86_64-linux-kernel --print target-cpus
Available CPUs for this target:
native - Select the CPU of the current host (currently bdver4).
编译时:
$ cargo build --release
时间是:
$ time target/release/sotest
real 0m1.668s
user 0m1.667s
sys 0m0.001s
但是对于“本地”目标,它运行得更慢:
$ RUSTFLAGS="-C target-cpu=native" cargo build --release
...
$ time target/release/sotest
real 0m2.783s
user 0m2.778s
sys 0m0.004s
问题是“本地”目标有什么问题-cpu?第一眼看到 documentation,我希望二进制文件利用我 CPU 提供的所有扩展:
The compiler will translate this into a list of target features.
即使不考虑扩展,为什么会变慢?
顺便说一句,编译选择 avx 扩展会产生很大的提升:
RUSTFLAGS="-C target-feature=+avx" cargo build --release
...
real 0m0.358s
user 0m0.354s
sys 0m0.004s
编辑:使用 Ubuntu 20.04 内核 5.4.0-72-generic。 rustc 1.51.0
我猜你遇到了这个错误:https://github.com/rust-lang/rust/issues/83027, which was resolved on March 17, 2021 by https://github.com/rust-lang/rust/pullis/83084。
错误是当使用 native
时,target_feature
没有正确应用,这是所有内在函数使用的。因此,您对内部函数的调用可能没有被内联。您应该查看配置文件以确认这一点。
更一般地说,我建议使用运行时 CPU 特征检测和正确使用 #[target_feature]
。您应该只从至少启用了 avx
功能的函数调用对 32 字节向量进行操作的函数。