Fearless SIMD v1.0
Fearless SIMD v1.0 (linebender.org)
要約
Rust向けのSIMD(Single Instruction, Multiple Data)ライブラリであるFearless SIMDがバージョン1.0に到達しました。このライブラリは、SIMD処理における`unsafe`コードの必要性を排除し、パフォーマンスと安全性を両立させることを目指しています。ポータブルな抽象化、プラットフォーム固有のイントリンシックへの安全なアクセス、そして使いやすいマクロを提供します。
全文翻訳
Fearless SIMD v1.0 が登場
Shnatsel, 2026年9月22日
fearless_simd は、SIMDからunsafeを取り除きます。
8年前の最初のプロトタイプから長い道のりを経てきました。現在、オートベクター化やマルチバージョン化だけが必要な場合でも、本格的なポータブルSIMD抽象化が必要な場合でも、あるいはイントリンシックへの安全なアクセスだけが必要な場合でも、Fearless SIMDが皆様のお役に立てると確信しています。
Changelogを言い換える代わりに、この機会にFearless SIMDの目標、それをどのように達成しているか、そして他のSIMD抽象化と何が違うのかについて考察したいと思います。
パフォーマンス
ポータブルSIMD抽象化によく寄せられる批判は、パフォーマンスが十分ではないというものです。そのため、Fearless SIMDが決して皆様の足を引っ張らないように、多大な努力を払ってきました。
例えば、スウィズルや浮動小数点数の最大値のように、エッジケースでの動作がプラットフォームごとに異なる操作のためのポータブル抽象化を実装する際には、すべてのプラットフォームで同じ結果を返す正確なバリアントと、エッジケースが発生しないと予想される場合にプラットフォーム依存の結果を返す高速なバリアントの両方を提供しています。
また、ハードウェアのネイティブベクトルサイズでSIMDアルゴリズムを表現することを容易にしました。これにより、コードはどこで実行されても、常にハードウェアを最大限に活用できます。固定ベクトルサイズのサポートも、それが必要なアルゴリズムのために提供されています。
さらに、ポータブルSIMD操作の実装が最先端であることを保証するために多大な努力を払い、RustとLLVMの両方に改善を貢献しました。
しかし、ポータブル抽象化でカバーされていない命令が必要な場合や、さらに制御したい場合は、コードの必要な部分に対してオーバーヘッドなしで、プラットフォームイントリンシックに安全にドロップダウンでき、残りの部分はシンプルでポータブルに保つことができます。
イントリンシックへの安全なアクセスのおかげで、パフォーマンスの天井は存在しません。
安全性
他のSIMD抽象化のソースコードを調べると、unsafeコードでいっぱいであることがわかります。rg unsafeのような検索では、数千ものunsafeブロックが見つかるでしょう。
しかし、Fearless SIMDではそうではありません!このクレートは、アドホックなunsafeコードを必要としないように慎重に設計されています。
このパズルのピースの一つがkernel!マクロです。これは、コンパイラのtarget feature v1.1に依存して、ほとんどのSIMDイントリンシックをunsafeなしで呼び出します。この設計については、以前のブログ記事で詳細に説明しましたので、さらに詳しく知りたい方はそちらをご覧ください。
これにより、アドホックなunsafeのほとんどが除去されますが、生のポインタを操作するSIMDのロード/ストア操作はカバーされません。そこで、bytemuckやzerocopyのようなクレートに触発された、私たちの安全なtransmuteモジュールが登場します。
_mm_loadu_epi32のようなSIMDイントリンシックは特別に見えるかもしれませんが、実際には裏側では通常のロードとストアに変換されます。そのため、単一の再利用可能なラッパーでその機能を完全に再現できます。
Rustの型システムの力のおかげで、監査する必要があるのは、これら2つの小さく自己完結したビルディングブロックだけです。それらがメモリ安全であれば、コードベースの残りの部分もメモリ安全であることが保証されます。
ついに、RustでのSIMDは真に恐れを知らぬものになりました。
エルゴノミクス
関数マルチバージョン化はトリッキーです。
以前のソリューションは、 #[inline(always)] アノテーションを追加する必要があるか、その意味を理解する必要がありました。あるいは、すべての関数呼び出しに小さなオーバーヘッドが課せられるというものでした。後者はほとんどの場合問題ありませんが、非常に小さな関数ではパフォーマンスが低下し、それを回避するために外科的に#[inline(always)]を追加する必要がありました。
どちらもリーキーな抽象化です。つまり、裏側で何が起こっているのかをまだ考える必要があります!
fearless_simd v1.0と同時に、fearless_simd_macros v0.1をリリースします。これは、リーキーではない抽象化、つまり#[simd]マクロを提供します。これを使えば、裏側で何が起こっているのかを全く考える必要がありません!任意のSIMD関数に適用すれば、ただ動作します。
とはいえ、これはエコシステムにとって大きな一歩ですが、まだいくらかのボイラープレートが関わっています。私たちは、コンパイラサポート(Struct Target Features RFCによる#[simd]アノテーションの完全な削除)や、将来探求するであろう他のトリックによって、それをさらに削減することに熱心です。
プロシージャルマクロが気に入らない場合は、古いやり方も引き続き利用可能ですが、利便性は低下します。
エルゴノミクスは、まだ進化する可能性があると予想される分野です。しかし、これはコアfearless_simdクレートの安定性保証を損なうものではなく、今日#[simd]マクロの有無にかかわらず書かれたコードは、無期限に動作し続けます。
安定性
Fearless SIMDはここに留まります。v1.0およびそれ以降のすべてのバージョンに対して、3年間のセキュリティアップデートを提供します。
未来を見通すことはできませんが、f16型のような短期的なRust機能と、SVEやRISC-V Vector Extensionのような長期的な機能(これらのハードウェア拡張が関連性を持つようになった場合)の両方を、API破壊的な変更なしにサポートするための実行可能なパスがあります。
std::simdとの関係
std::simdが安定化されることを願っていますが、それはFearless SIMDを時代遅れにするものではありません。
Rust標準ライブラリは、絶対に必要とされる部分のみを実装しており、残りの部分(例: マルチバージョン化、ハードウェア幅ベクトル)はエコシステムクレートに委ねられています。
fearless_simdには、安定版Rustで動作するstd::simdの同等物が含まれていますが、それはより大きな全体の一部にすぎません。
std::simdが安定化されたら、Fearless SIMDをそれに移植して、多くのカスタムコードを削除し、あらゆる種類のマイナーなプラットフォームのサポートを得る予定です。しかし、fearless_simdのようなエコシステムクレートの必要性は残ります。
採用
クレートがどれほど優れていても、誰も使っていなければ意味がありません。
Fearless SIMDはすでに30の他のクレートに直接依存されており、1000以上のクレートに間接的に依存されています!
すでにRustエコシステムの相当な部分を支えており、v1.0がこれをさらに前進させることを願っています。
プロジェクトでFearless SIMDを使用したい場合は、ドキュメントと例をご覧ください。質問があれば、Zulipで遠慮なくお尋ねください!