2 个版本
0.1.1 | 2022 年 7 月 3 日 |
---|---|
0.1.0 | 2022 年 7 月 3 日 |
#1318 in 硬件支持
9KB
69 行
slices_dispatch_wide!
一个宏,用于通过使用 wide
包进行 SIMD 操作,将向量化数学操作调度到切片上
此库会遍历切片的块,将它们转换为来自 wide 包的类型,并在这些块和剩余的标量元素上调度一些数学操作。此库并非在所有情况下都适用,不会对对齐进行特殊处理,而且可能无法胜过最佳的可能手动调整的 SIMD 代码。尽管如此,如果它适用于您的用例,它将使您的生活更加轻松。
此库最有用的情况是
- 您需要在今天的稳定 Rust 上执行 SIMD 数学操作(例如
sqrt
、log
、exp
等)。 - 您不想引入非 Rust 库或使您的构建过程复杂化以执行此操作。
- 您需要同时迭代长度相同的多个切片,并且至少修改其中一个。
- 您不想重复自己或编写样板代码。
- 您不需要可变通道宽度。
示例
use slices_dispatch_wide::*;
let mut a = [1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0];
let b = [2.0_f64, 2.0, 2.0, 2.0, 2.0, 2.0];
// Dispatches using chunks/SIMD types of width 4
slices_dispatch_wide!(4, |a => a mut: f64, b => b: f64| {
// We can mutate the slices when the mut keyword is specified as it is above
a += b;
});
// Notice that the number of elements is not a multiple of the SIMD width, the remainder is
// taken care of with scalar operations
assert_eq!(a, [3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
// We can also do some fancier math operations in place
slices_dispatch_wide!(2, |a => a mut: f64| {
a = a.powf(2.0);
});
assert_eq!(a, [9.0, 16.0, 25.0, 36.0, 49.0, 64.0]);
// You can assign different names to the elements from the slices you use
// And you can mutate multiple variables at the same time
let mut some_container = ([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], "test", 0);
let mut c = [4.0, 2.0, 1.0, 0.0, 1.0, 2.0];
slices_dispatch_wide!(4, |some_container.0 => sc mut: f64, c => d mut: f64| {
sc += d;
d += sc;
});
assert_eq!(some_container.0, [5.0, 4.0, 4.0, 4.0, 6.0, 8.0]);
assert_eq!(c, [9.0, 6.0, 5.0, 4.0, 7.0, 10.0]);
// If you need to get the result in a new array/vector, you can pre-allocate it
let mut d = [0.0; 6];
slices_dispatch_wide!(4, |some_container.0 => sc: f64, d => d mut: f64| {
d = 2.0 * sc;
});
assert_eq!(d, [10.0, 8.0, 8.0, 8.0, 12.0, 16.0]);
注意,如果切片长度不匹配,此宏将引发恐慌
// This example will panic because the lengths are different
use slices_dispatch_wide::*;
let a = [0u32];
let b = [0u32, 1];
slices_dispatch_wide!(8, |a => a: u32, b => b: u32| {});
并且宽度必须是字面量
// This example will not compile because the width is not a literal
use slices_dispatch_wide::*;
let a = [0u32];
let b = [0u32];
slices_dispatch_wide!(4 + 4, |a => a: u32, b => b: u32| {});
注意事项
- 使用的 SIMD 类型(每个切片使用的通道宽度和标量类型的组合)必须在 wide 包中存在。
- 块中的代码必须在迭代变量是给定的标量类型或相应的 SIMD 类型时有效。
许可证
在任何以下许可证下授权
- Apache 许可证 2.0 版,(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 https://opensource.org/licenses/MIT)
- Zlib 许可证 (LICENSE-ZLIB 或 https://opensource.org/licenses/Zlib)
供您选择。
依赖项
~1.5MB
约~30K SLoC