fearless_simd v0.7: 64-bit integers, improved generics, SSE2, and upcoming v1.0

fearless_simd v0.7: 64-bit integers, improved generics, SSE2, and upcoming v1.0

fearless_simd v0.7:64位整数、改进的泛型、SSE2 以及即将到来的 v1.0

Shnatsel, August 10, 2026 Shnatsel,2026年8月10日

fearless_simd takes unsafe out of SIMD. No matter what level of abstraction you’re after, be it autovectorization and multiversioning, portable SIMD, or safe access to raw intrinsics and nothing more, fearless_simd has you covered! It features zero dependencies, short build times, safe public APIs, and very little unsafe under the hood - orders of magnitude less than the alternatives! fearless_simd 将 unsafe 从 SIMD 中移除。无论您追求何种抽象级别——无论是自动向量化和多版本分发、可移植 SIMD,还是仅仅是安全地访问原始内联函数(intrinsics)——fearless_simd 都能满足您的需求!它具有零依赖、构建时间短、公共 API 安全以及底层 unsafe 代码极少等特点,其 unsafe 代码量比同类方案少了几个数量级!

The major additions in v0.7 are support for 64-bit integers, an explicit SSE2 level replacing scalar fallback on x86, improved support for generic programming, and more implemented SIMD operations. This is also the last major release prior to Fearless SIMD v1.0, if no concerns about the API are raised. v0.7 的主要新增功能包括:支持 64 位整数、用于替代 x86 上标量回退(scalar fallback)的显式 SSE2 级别、改进的泛型编程支持,以及更多已实现的 SIMD 操作。如果 API 没有引发其他问题,这将是 Fearless SIMD v1.0 之前的最后一个主要版本。

64-bit integers

64位整数

The entire API surface of fearless_simd is now also exposed for u64 and i64 vector types. Earlier releases didn’t support 64-bit integer vectors due to hardware support being spotty. For example, AVX2 lacks hardware support for many operations on 64-bit integers, so it would require emulation using the available SIMD instructions for those operations to get decent performance. Keeping track of which intrinsics are part of which instruction set was also challenging, and getting it wrong would be a memory safety violation. However, in v0.5 we made the compiler keep track of it for us, which removed the vast majority of unsafe blocks from fearless_simd and made implementing operations with uneven hardware support much easier. All the other integer vector types (i8,u8,i16,u16,i32,u32) and f32/f64 were already supported by previous releases, so 64-bit integers were the last missing piece for full type coverage. We will investigate supporting f16 once the type is stabilized in the standard library. fearless_simd 的整个 API 现已全面支持 u64 和 i64 向量类型。早期版本不支持 64 位整数向量,因为硬件支持参差不齐。例如,AVX2 缺乏对许多 64 位整数操作的硬件支持,因此需要使用现有的 SIMD 指令进行模拟才能获得不错的性能。跟踪哪些内联函数属于哪个指令集也极具挑战性,一旦出错就会导致内存安全违规。然而,在 v0.5 中,我们让编译器代为跟踪,这消除了 fearless_simd 中绝大多数的 unsafe 代码块,并使实现硬件支持不均衡的操作变得容易得多。所有其他整数向量类型(i8, u8, i16, u16, i32, u32)以及 f32/f64 在之前的版本中已得到支持,因此 64 位整数是实现完全类型覆盖的最后一块拼图。一旦 f16 类型在标准库中稳定下来,我们将研究对其提供支持。

More operations

更多操作

swizzle_dyn is now implemented for all widths to allow arbitrary byte shuffles. I’ve also contributed performance improvements for this operation to std::simd. Unlike std::simd, Fearless SIMD supports both zeroing out-of-bounds indices and returning implementation-defined (but memory-safe) results for when you’re sure all indices are in bounds, which is cheaper than zeroing on some platforms. All types can now be widened/narrowed; e.g. you can convert vectors of u8 to u16, or u16 to u8 in SIMD code. You get to choose whether narrowing conversions wrap, like the as operator, or saturate, or do the cheapest thing the platform has to offer (useful if you’re sure the values fit into the narrower type). Added convenience functions shift_elements_left, shift_elements_right, rotate_elements_left, and rotate_elements_right for better compatibility with the std::simd API. They could already be implemented in terms of slide, but this makes the intent more clear. swizzle_dyn 现已在所有宽度上实现,允许进行任意字节重排。我还为 std::simd 贡献了该操作的性能改进。与 std::simd 不同,Fearless SIMD 既支持将越界索引置零,也支持在确定所有索引都在范围内时返回由实现定义(但内存安全)的结果,这在某些平台上比置零开销更小。现在所有类型都可以进行扩宽/缩窄转换;例如,您可以在 SIMD 代码中将 u8 向量转换为 u16,或将 u16 转换为 u8。您可以选择缩窄转换是像 as 运算符那样进行截断(wrap)、饱和(saturate),还是执行平台提供的开销最小的操作(如果您确定数值适合较窄的类型,这非常有用)。新增了 shift_elements_leftshift_elements_rightrotate_elements_leftrotate_elements_right 等便捷函数,以更好地兼容 std::simd API。虽然它们之前可以通过 slide 实现,但这些函数使代码意图更加清晰。

Improved generic programming

改进的泛型编程

Support for generic programming - writing functions that are generic over the vector type - has been substantially improved. Here are just a few highlights: The SimdBase trait now abstracts over both integer and float vectors, and implements all methods available on both integers and floats. Improvements to the Bytes trait allow generic bitcasts (safe transmutes) between SIMD vectors. Every single operation on SIMD types is now available through a trait. There are no remaining operations implemented only for concrete types. Associated types such as SimdBase::Element and SimdBase::Array now encode a lot of generic bounds to allow generic operations on them. See the full changelog for details. All in all, generic SIMD programming is now much more pleasant, and allows expressing more algorithms generically. These improvements also benefit users who abstract over SIMD vector types using macros, writing e.g. $type::from_slice instead of T::from_slice. They no longer need additional crates such as paste to inject types into function names, since all operations are now available on the types themselves. 泛型编程的支持——即编写针对向量类型通用的函数——得到了显著改进。以下是几个亮点:SimdBase trait 现在同时抽象了整数和浮点向量,并实现了整数和浮点数上可用的所有方法。对 Bytes trait 的改进允许在 SIMD 向量之间进行泛型位转换(安全转换)。现在,SIMD 类型上的每一个操作都可以通过 trait 访问。不再有仅针对具体类型实现的操作。诸如 SimdBase::ElementSimdBase::Array 之类的关联类型现在编码了许多泛型约束,以允许对其进行泛型操作。详情请参阅完整更新日志。总而言之,泛型 SIMD 编程现在更加顺手,并允许以更通用的方式表达算法。这些改进也惠及那些使用宏来抽象 SIMD 向量类型的用户,例如编写 $type::from_slice 而不是 T::from_slice。他们不再需要像 paste 这样的额外 crate 来将类型注入函数名,因为所有操作现在都直接在类型本身上可用。

Explicit SSE2 support

显式 SSE2 支持

These days x86 systems without SSE4.2 are very rare. However, since SSE2 is part of the baseline instruction set in both x86_64 and i686 Rust targets, the presence of SSE2 can be assumed, without any runtime dispatch or multiversioning. Certain crates only need a very limited set of vector instructions and don’t benefit from later extensions, so forgoing runtime dispatch can simplify the code and reduce binary size. To better serve this use case, Fearless SIMD now has an explicit Sse2 level with operations expressed in terms of SIMD intrinsics, rather than relying on autovectorization of the Fallback level when SSE4.2 is not available. This improves performance on x86 when the user opts out of selecting the best SIMD implementation at runtime. SSE2 remains a runtime-detected level on the tier-2 i586 targets, and can be disabled there using the usual multiversioning controls. 如今,没有 SSE4.2 的 x86 系统非常罕见。然而,由于 SSE2 是 x86_64 和 i686 Rust 目标架构的基准指令集的一部分,因此可以假定 SSE2 始终存在,无需任何运行时分发或多版本控制。某些 crate 只需要非常有限的一组向量指令,且无法从后续扩展中获益,因此放弃运行时分发可以简化代码并减小二进制体积。为了更好地服务于这种用例,Fearless SIMD 现在提供了一个显式的 Sse2 级别,其操作通过 SIMD 内联函数表达,而不是在 SSE4.2 不可用时依赖 Fallback 级别的自动向量化。当用户选择不在运行时选择最佳 SIMD 实现时,这提高了 x86 上的性能。在二级 i586 目标上,SSE2 仍然是一个运行时检测级别,并可以使用常规的多版本控制进行禁用。

Build time improvements

构建时间改进

Despite the addition of 64-bit integer vectors, more supported operations, and an entirely new SSE2 SIMD level, the compilation time of fearless_simd when used as a dependency stayed the same as v0.6: 2 seconds from scratch for x86 and 1 second from scratch for Aarch64. This was measured on my Zen 4 desktop CPU via cargo clean && cargo build --release --timings in an empty crate depending on fearless_simd. Keeping compilation time unchanged despite the additions required a build profiling and optimization effort, without which the x86 build time would have increased to 3.4 seconds on my machine. It’s still not that much for a from-scratch release build, and would have been entirely invisible for crates that have other dependency chains that take longer than 3.4 seconds to compile. But I believe that keeping build times low is important for Fearless SIMD to become a foundational SIMD abstraction. This is also a big part of why fearless_simd doesn’t have any dependencies itself. The vast majority of the fearless_simd API is made up of generic functions. They emit no machine code unless instantiated, so… 尽管增加了 64 位整数向量、更多支持的操作以及全新的 SSE2 SIMD 级别,fearless_simd 作为依赖项时的编译时间仍与 v0.6 保持一致:x86 从零构建为 2 秒,Aarch64 从零构建为 1 秒。这是在我的 Zen 4 台式机 CPU 上,通过在一个依赖 fearless_simd 的空 crate 中运行 cargo clean && cargo build --release --timings 测得的。为了在增加功能的同时保持编译时间不变,我进行了构建分析和优化工作,否则 x86 的构建时间在我的机器上会增加到 3.4 秒。对于从零开始的发布构建来说,这并不算多,而且对于那些拥有其他编译时间超过 3.4 秒的依赖链的 crate 来说,这几乎是不可察觉的。但我认为,保持较低的构建时间对于 Fearless SIMD 成为基础 SIMD 抽象至关重要。这也是 fearless_simd 本身没有任何依赖项的重要原因。fearless_simd API 的绝大部分由泛型函数组成。除非被实例化,否则它们不会生成机器码,因此……