刚开始使用Rust的std::simd
库,我发现自己遇到了这样的情况:
我有一个Mask8x8和一个u8x8,如果相应的掩码为FALSE,我想将u8x8中的每个通道设置为0;基本上我想将它们相乘,假设掩码与SIMD的布局相同.
不过,我找不到比使用mask.select(foo, u8x8::splat(0))
更好的方法了,这似乎效率低下/很难读懂.当然有更好的方法来做到这一点吗?
刚开始使用Rust的std::simd
库,我发现自己遇到了这样的情况:
我有一个Mask8x8和一个u8x8,如果相应的掩码为FALSE,我想将u8x8中的每个通道设置为0;基本上我想将它们相乘,假设掩码与SIMD的布局相同.
不过,我找不到比使用mask.select(foo, u8x8::splat(0))
更好的方法了,这似乎效率低下/很难读懂.当然有更好的方法来做到这一点吗?
我认为std::simd
没有足够的 solidity 来讨论最佳实践,特别是在 compose 本文时,您可以看到在官方的feature roadmap中,"What are the ideal semantics for Masks?"点还没有复选标记.因此,您可以期待此API在稳定之前会有所改善.
也就是说,多亏了Rust的特征系统,你总是可以自己扩展功能集,如下所示:
use std::simd;
trait SimdExt<T, const N: usize>
where
T: simd::SimdElement + Default,
simd::LaneCount<N>: simd::SupportedLaneCount,
{
fn filter(self, mask: simd::Mask<T::Mask, N>) -> Self;
}
impl<T, const N: usize> SimdExt<T, N> for simd::Simd<T, N>
where
T: simd::SimdElement + Default,
simd::LaneCount<N>: simd::SupportedLaneCount,
{
fn filter(self, mask: simd::Mask<T::Mask, N>) -> Self {
mask.select(self, simd::Simd::<T, N>::splat(Default::default()))
}
}
然后,您应该能够写出:
use std::simd::{mask8x8, u8x8, ToBitMask};
fn main() {
let data = u8x8::from_array([1, 2, 3, 4, 5, 6, 7, 8]);
let mask = mask8x8::from_bitmask(0b01010110);
let filtered_data = data.filter(mask);
println!("{:?}", filtered_data);
}
[0, 2, 3, 0, 5, 0, 7, 0]
证明这等同于您的代码:https://rust.godbolt.org/z/354e5srh8