2 个版本

使用旧的 Rust 2015

0.1.1 2018年11月5日
0.1.0 2018年10月19日

#1244 in 硬件支持

MIT/Apache

41KB
1K SLoC

向“无惧 SIMD”迈进

此crate提供安全的封装,使编写SIMD代码更加容易。它尚未实现“无惧 SIMD”的承诺,但展示了一条实现这一目标的潜在路径。

它试图解决以下问题

  • 自动检测CPU级别并运行最佳代码。

  • 使用时无需 unsafe

  • 访问高级SIMD原语,如舍入和近似倒数。

  • 与稳定版 Rust 兼容。

  • 可在多个架构上移植(但当前稳定版 Rust 仅支持 x86 - 可能将 arm 作为可选,以便在 nightly 编译)。

其应用范围有限

  • 专注于 f32。

  • 主要(但不完全是)为 1D 无结构数据提供映射和生成器。

  • 未尝试支持对齐加载/存储。在现代CPU上,非对齐的SIMD访问性能相当好,而对齐对程序员来说是一个非常大的负担。

该crate中的想法可能被扩展到更多应用中。

注意事项和未来展望

我在编写此crate时遇到了当前 Rust 的许多限制。我认为其中一些将会得到改进。我发布这个crate的部分原因是为了指出更多可能需要工作的地方。

错误地启用内联会触发 rust-lang/rust#50154。话虽如此,GeneratorF32 trait 的设计使得迭代器的创建发生在 target_feature 封装器内部,这应该既减少了触发该错误的机会,又提高了代码质量。

该错误不是内联误功能的唯一问题;#[cfg(target_feature)] 宏解析得太早,并且如果函数被内联,则不报告是否启用了该功能。这一点在 rust-internals 线程 中有所讨论。在我看来,提议的方法 并没有真正解决这个问题,因为运行时功能并不总是与 [target_feature(enabled)] 匹配。例如,运行时功能检测可能会显示 AVX-512 可用,但用户可能会出于性能原因选择仅使用 AVX2。

我希望使 GeneratorF32 特性处理器无关且完全通用。换句话说,我想要能够编写这样的代码

pub trait GeneratorF32: Sized {
    type Iter<S: SimdF32>: Iterator<Item=S>;
    fn gen<S>(self, cap: S) -> Self::Iter<S>;
}

该功能正在开发中:泛型关联类型](rust-lang/rust#44265)。

如果 x 有一个 SimdF32 值,那么可以编写类似这样的代码,例如 x + 1.0,但到目前为止,1.0 + x 不起作用。如果将相关特性界限添加到 SimdF32 特性,这些界限将起作用,但这将迫使客户端实现中产生大量的样板代码,因为 rust-lang/rust#23856。当 Chalk 出现时,这可能会得到改善。

我使用 SimdFnF32 特性来表示一个函数在实际的 SIMD 类型上是通用的。更好的是,可以像这样

pub trait GeneratorF32: Sized {
    fn map<F>(self, f: F) where F: for<S: SimdF32> Fn(S) -> S;
}

目前,for<> 语法适用于更高阶的生命周期,但不适用于一般的高阶泛型。我不确定这会发生,但这展示了一个为什么这些奇特的更高阶类型可能有用的实际例子。

与其他方法的比较

faster 中得到了很多灵感,它有类似的目标。然而,faster 依赖于编译时特性确定,似乎无法在运行时切换。

安全包装的灵感来自 packed_simd。这个 crate 希望暴露更大的 SIMD 片段,但将运行时特性检测留给用户。

C/C++ 生态系统在这个领域做了很多工作。他们有一个相当复杂的 函数多版本化 机制,运行时检测由动态加载器解决。在很大程度上,这个 crate 试图获得其中的一些好处,而无需对语言或实现进行扩展。然而,这个 crate “占用”了多维度或两维的多态类型空间,所以这是一个需要考虑的权衡。

基准测试

这些不是严格意义上的,但应该给出性能的一般印象。特定的基准是生成小于 -100dB 失真的正弦波,时间以 ns 计,生成 64 个样本。

CPU simd 级别 时间
i7 7700HQ AVX 30
" SSE 4.2 49
" 标量回退 344
" sin() 标量 506
i5 430M SSE4.2 303
" 标量回退 717
" sin() 标量 1690

致谢

错误(包括对走这条路的判断)是我自己的,但我从与许多人的讨论中受益,包括与 James McCartney、Andrew Gallant(《burntsushi》)、《talchas》、《Colin Rofls》和 Alex Crichton 的讨论。

无运行时依赖