14 个版本

0.5.2 2021年3月25日
0.5.1 2020年6月28日
0.5.0 2018年7月21日
0.4.3 2018年1月28日
0.1.5 2017年11月12日

#493 in 硬件支持

MPL-2.0 许可证

565KB
10K SLoC

  • faster #+BEGIN_HTML#+END_HTML

** 人类的 SIMD,简单、强大、便携、速度极快的数据计算。包括基于您平台的静态调度和内联以及向量类型、零分配迭代、向量加载/存储和不等集合支持。

它看起来可能像这样: #+BEGIN_SRC rust use faster::*;

let lots_of_3s = (&[-123.456f32; 128][..]).simd_iter() .simd_map(f32s(0.0), |v| { f32s(9.0) * v.abs().sqrt().rsqrt().ceil().sqrt() - f32s(4.0) - f32s(2.0) }) .scalar_collect(); #+END_SRC

这类似于以下标量代码: #+BEGIN_SRC rust let lots_of_3s = (&[-123.456f32; 128][..]).iter() .map(|v| { 9.0 * v.abs().sqrt().sqrt().recip().ceil().sqrt() - 4.0 - 2.0 }) .collect::<Vec>(); #+END_SRC

向量大小完全由您编译的目标机器决定 - 它会尝试使用机器支持的最大的向量大小,并在任何平台或架构上工作(详细信息请见下文)。

将其与传统显式 SIMD 进行比较: #+BEGIN_SRC rust use std::mem::transmute; use stdsimd::{f32x4, f32x8};

let lots_of_3s = &mut [-123.456f32; 128][..];

如果cfg!(all(not(target_feature = "avx"), target_feature = "sse")) { for ch in init.chunks_mut(4) { let v = f32x4::load(ch, 0); let scalar_abs_mask = unsafe { transmute::(0x7fffffff) }; let abs_mask = f32x4::splat(scalar_abs_mask); // 实际上没有为浮点数提供绝对值内建函数 - 你需要查看IEEE 754规范并进行一些位翻转 v = unsafe { _mm_and_ps(v, abs_mask) }; v = unsafe { _mm_sqrt_ps(v) }; v = unsafe { _mm_rsqrt_ps(v) }; v = unsafe { _mm_ceil_ps(v) }; v = unsafe { _mm_sqrt_ps(v) }; v = unsafe { _mm_mul_ps(v, 9.0) }; v = unsafe { _mm_sub_ps(v, 4.0) }; v = unsafe { _mm_sub_ps(v, 2.0) }; f32x4::store(ch, 0); } } else if cfg!(all(not(target_feature = "avx512"), target_feature = "avx")) { for ch in init.chunks_mut(8) { let v = f32x8::load(ch, 0); let scalar_abs_mask = unsafe { transmute::(0x7fffffff) }; let abs_mask = f32x8::splat(scalar_abs_mask); v = unsafe { _mm256_and_ps(v, abs_mask) }; v = unsafe { _mm256_sqrt_ps(v) }; v = unsafe { _mm256_rsqrt_ps(v) }; v = unsafe { _mm256_ceil_ps(v) }; v = unsafe { _mm256_sqrt_ps(v) }; v = unsafe { _mm256_mul_ps(v, 9.0) }; v = unsafe { _mm256_sub_ps(v, 4.0) }; v = unsafe { _mm256_sub_ps(v, 2.0) }; f32x8::store(ch, 0); } } #+END_SRC 即使有这么多模板代码,这仍然只支持具有SSE或AVX的x86-64机器 - 你必须查找每个内建函数以确保它适用于你的编译目标。 ** 即将到来的功能 预计将重写迭代器API,以及进行内部更改,以更好地适应Rust对显式SIMD的采用方向。 ** 兼容性 Faster目前支持任何具有浮点支持的架构,尽管仅在具有x86向量扩展的机器上启用硬件加速。 ** 性能 这里有一些非常不科学的基准测试,至少可以证明这并不比标量迭代器差。即使在古老的CPU上,也可以从SIMD中提取出很多性能。

#+BEGIN_SRC shell $ RUSTFLAGS="-C target-cpu=ivybridge" cargo bench # 主机是ivybridge;目标有AVX测试 tests::base100_enc_scalar ... 基准:1,307 ns/iter (+/- 45) test tests::base100_enc_simd ... 基准:332 ns/iter (+/- 10) test tests::determinant2_scalar ... 基准:486 ns/iter (+/- 8) test tests::determinant2_simd ... 基准:215 ns/iter (+/- 3) test tests::determinant3_scalar ... 基准:389 ns/iter (+/- 6) test tests::determinant3_simd ... 基准:209 ns/iter (+/- 3) test tests::map_fill_simd ... 基准:835 ns/iter (+/- 12) test tests::map_scalar ... 基准:6,963 ns/iter (+/- 117) test tests::map_simd ... 基准:879 ns/iter (+/- 18) test tests::map_uneven_simd ... 基准:884 ns/iter (+/- 10) test tests::nop_scalar ... 基准:49 ns/iter (+/- 0) test tests::nop_simd ... 基准:34 ns/iter (+/- 0) test tests::reduce_scalar ... 基准:6,905 ns/iter (+/- 107) test tests::reduce_simd ... 基准:839 ns/iter (+/- 13) test tests::reduce_uneven_simd ... 基准:838 ns/iter (+/- 11) test tests::zip_nop_scalar ... 基准:824 ns/iter (+/- 18) test tests::zip_nop_simd ... 基准:231 ns/iter (+/- 5) test tests::zip_scalar ... 基准:901 ns/iter (+/- 29) test tests::zip_simd ... 基准:1,128 ns/iter (+/- 12)

RUSTFLAGS="-C target-cpu=x86-64" cargo bench # 主机是 ivybridge;目标有 SSE2 测试 tests::base100_enc_scalar ... 基准: 760 ns/iter (+/- 11) 测试 tests::base100_enc_simd ... 基准: 492 ns/iter (+/- 2) 测试 tests::determinant2_scalar ... 基准: 477 ns/iter (+/- 3) 测试 tests::determinant2_simd ... 基准: 277 ns/iter (+/- 1) 测试 tests::determinant3_scalar ... 基准: 380 ns/iter (+/- 3) 测试 tests::determinant3_simd ... 基准: 285 ns/iter (+/- 2) 测试 tests::map_fill_simd ... 基准: 1,797 ns/iter (+/- 8) 测试 tests::map_scalar ... 基准: 7,237 ns/iter (+/- 51) 测试 tests::map_simd ... 基准: 1,879 ns/iter (+/- 12) 测试 tests::map_uneven_simd ... 基准: 1,878 ns/iter (+/- 9) 测试 tests::nop_scalar ... 基准: 47 ns/iter (+/- 0) 测试 tests::nop_simd ... 基准: 34 ns/iter (+/- 0) 测试 tests::reduce_scalar ... 基准: 7,021 ns/iter (+/- 39) 测试 tests::reduce_simd ... 基准: 1,801 ns/iter (+/- 8) 测试 tests::reduce_uneven_simd ... 基准: 1,734 ns/iter (+/- 9) 测试 tests::zip_nop_scalar ... 基准: 803 ns/iter (+/- 9) 测试 tests::zip_nop_simd ... 基准: 257 ns/iter (+/- 1) 测试 tests::zip_scalar ... 基准: 988 ns/iter (+/- 6) 测试 tests::zip_simd ... 基准: 629 ns/iter (+/- 5)

$ RUSTFLAGS="-C target-cpu=pentium" cargo bench # 主机是 ivybridge;此仅运行填充函数!测试 tests::bench_determinant2_scalar ... 基准: 427 ns/iter (+/- 2) 测试 tests::bench_determinant2_simd ... 基准: 402 ns/iter (+/- 1) 测试 tests::bench_determinant3_scalar ... 基准: 354 ns/iter (+/- 1) 测试 tests::bench_determinant3_simd ... 基准: 593 ns/iter (+/- 1) 测试 tests::bench_map_scalar ... 基准: 7,195 ns/iter (+/- 28) 测试 tests::bench_map_simd ... 基准: 6,271 ns/iter (+/- 22) 测试 tests::bench_map_uneven_simd ... 基准: 6,288 ns/iter (+/- 22) 测试 tests::bench_nop_scalar ... 基准: 38 ns/iter (+/- 0) 测试 tests::bench_nop_simd ... 基准: 69 ns/iter (+/- 0) 测试 tests::bench_reduce_scalar ... 基准: 7,004 ns/iter (+/- 17) 测试 tests::bench_reduce_simd ... 基准: 6,063 ns/iter (+/- 17) 测试 tests::bench_reduce_uneven_simd ... 基准: 6,107 ns/iter (+/- 11) 测试 tests::bench_zip_nop_scalar ... 基准: 623 ns/iter (+/- 2) 测试 tests::bench_zip_nop_simd ... 基准: 289 ns/iter (+/- 1) 测试 tests::bench_zip_scalar ... 基准: 972 ns/iter (+/- 3) 测试 tests::bench_zip_simd ... 基准: 621 ns/iter (+/- 3) #+END_SRC

依赖项

~1.5MB
~30K SLoC