2 个版本
使用旧的 Rust 2015
0.1.1 | 2018年11月5日 |
---|---|
0.1.0 | 2018年10月19日 |
#1244 in 硬件支持
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 的讨论。