刚开始使用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

Rust相关问答推荐

关联类型(类型参数)命名约定

支持TLS的模拟HTTP服务器

如何正确地将App handler传递给Tauri中的其他模块?

`Pin`有没有不涉及不安全代码的目的?

当发送方分配给静态时,Tokio MPSC关闭通道

完全匹配包含大小写的整数范围(&Q;)

零拷贝按步骤引用一段字节

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

为什么 vec![Vec::with_capacity(n)] 为子向量创建 0 容量?

UnsafeCell:它如何通知 rustc Select 退出基于别名的优化?

在 Rust 中,是否可以定义一个需要实现类型的构造函数的对象安全特征?

在Rust中实现Trie数据 struct 的更好方式

为什么 Rust 的临时值有时有参考性有时没有?

Rust 中 Mutex<> 的深拷贝?

如果不满足条件,如何在 Rust 中引发错误

如何创建递归borrow 其父/创建者的 struct ?

使用方法、关联函数和自由函数在 Rust 中初始化函数指针之间的区别

如何在 Rust 中创建最后一个元素是可变长度数组的 struct ?

如果我立即等待,为什么 `tokio::spawn` 需要一个 `'static` 生命周期?

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?