Rust 1.27 支持 SIMD

阅读数:527 2018 年 6 月 27 日

话题:语言 & 开发Rust

SIMD 支持是Rust 1.27中最值得一提的新特性,这一版本的 Rust 同时还带来了更为明确的 trait 语法。

在语言层面支持 SIMD 意味着开发人员可以在更高级别上表达矢量化计算,并在编译器不够智能时超越编译器来应用自动矢量化。下面的例子展示了如何表示两个向量(或切片)的总,这两个向量分别包含了 16 个元素,每个元素为一个字节长度(u8)。每个切片可放入一个 128 位寄存器,因此我们可以将这两个片放入两个寄存器,并使用新的std :: arch 模块将它们添加到单个 CPU 指令中:

复制代码
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
target_feature = "avx2"))]
fn foo() {
#[cfg(target_arch = "x86")]
use std::arch::x86::_mm256_add_epi64;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::_mm256_add_epi64;
unsafe {
_mm256_add_epi64(...);
}
}

上面的代码片段还展示了如何为特定平台定制你的 SIMD 指令,因为不是所有运行你的代码的平台都可以支持 SIMD 操作。第一个 cfg 标记仅为指定平台(x86 或 x86_64 支持 AVX2)输出以下代码,而里面那个 cfg 标记将为特定平台选择正确的 _mm256_add_epi64 指令。

通过 std :: arch 提供支持 SIMD 只是 Rust 在 SIMD 支持方面迈出的第一步。事实上,Rust 已经计划了另一个模块 std :: simd,它将提供更高级别的操作。在 std :: simd 中可以通过faster crate,如用户可以使用 simd_iter 代替 iter,或使用 simd_map 代替 map 等,来完成 SIMD 版本的基本矢量操作。

该语言的另一个新功能旨在让 trait 语法更加明确,当给定 trait 对象对应一个或两个指针时,让表示更加清晰。trait 对象的表示语法如下:

复制代码
Box<Foo>

这个语法隐藏了一个事实,即当 Foo 是一个结构时,它将被简单地嵌入到 Box 中。相反,如果它是一个 trait,将被分配到堆上,并且一个指向它的 vtable 的指针将被分配到栈上。这是由于 Rust 中的 vtable 并不是与数据保存在一起的,而是分开存储,这个与 C++ 不一样。为了让这些更加明确,现在 Rust 支持一个新的 trait 语法(dyn trait):

复制代码
Box<dyn Foo>
&dyn Foo
&mut dyn Foo

旧的语法将保持不变,并且没有计划要弃用它。

最后,#[must_use] 属性现在可以用在函数上,让编译器标记这些忽略了函数返回值的情况:

复制代码
#[must_use]
fn double(x: i32) -> i32 {
2 * x
}
fn main() {
double(4); // warning: unused return value of `double` which must be used
let _ = double(4); // (no warning)
}

要详细了解 Rust 1.27,请不要错过官方发布说明。

查看英文原文Rust 1.27 Adds Support for SIMD