単一命令・複数データ(SIMD)のサポートは、Rust 1.27の最も注目すべき新機能であり、traitのための明示的な構文ともに提供される。
言語レベルでのSIMDサポートは、開発者がベクトル化された計算をより高レベルで表現でき、コンパイラが自動ベクトル化を適用する上で十分にスマートでない場合、コンパイラの性能を上回る可能性を意味する。以下は、16要素の2つのベクトル(またはスライス)の合計を表現する方法の例である。各要素は1バイト長(u8
)である。各スライスは1つの128ビットレジスタに収まるので、2つのスライスを2つのレジスタに入れ、新しい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
フラグは、指定されたプラットフォーム(AVX2
をサポートしているx86またはx86_64)の場合にのみ、続くコードを出力する一方、内側のcfg
フラグは特定のプラットフォームに対して正しい_mm256_add_epi64
命令を選択する。
std::arch
が提供するSIMDサポートは、Rust SIMDサポートの第一歩に過ぎない。実際には、std::simd
モジュールが既に計画されており、それによって高レベルの操作が提供される。std::simd
でできることの例は、よりfaster
クレートを通して提供される。これにより、iter
の代わりにsimd_iter
を、map
の代わりにsimd_map
を使うといったように、SIMD-ifiedバージョンの基本的なベクトル操作を使うことができる。
この言語のもう1つの新機能は、trait構文をより明示的にすることである。そして、与えられたtraitオブジェクトがただ1つのポインタまたは2つのポインタに対応するかを明確にすることを目的としている。traitオブジェクトを表すための基本構文は次のとおりである。
Box<Foo>
この構文は、Foo
が構造体である場合、それがBox
内に単純に埋め込まれるという事実を隠す。逆に、それがtraitであればヒープに割り当てられ、そのvtable
へのポインタがスタックに割り当てられる。これは、C++の場合と同様、Rustのvtableにデータが格納されていないためであり、故に別々に格納される。より明確に言うと、Rustは新しい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の詳細については、公式リリースノートを見逃さないようにしてください。
Rate this Article
- Editor Review
- Chief Editor Action