如何在Rust中求和一个字节数组?

时间:2014-04-16 05:15:29

标签: rust

  

编者注:这个问题的例子来自于1.0之前的Rust版本,以及在Rust中找不到的引用类型和方法。答案仍然包含有价值的信息。

以下代码

let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum(); 

只会导致以下错误:

std::iter::Map<,&u8,u8,std::slice::Items<,u8>>` does not implement any method in scope named `sum`

我必须做些什么来对一个字节数组求和?

BTW:以下作品:

for byte in new_serial.as_bytes().iter() {
    sum = sum + (byte - 48);
}

2 个答案:

答案 0 :(得分:5)

Iterator::sum在Rust 1.11.0中已稳定,可用作:

let new_serial = "01234";
let sum: u8 = new_serial.as_bytes().iter().map(|&x| x - 48).sum();
println!("{}", sum);

特别需要注意的是,您需要指定要汇总到的类型(sum: u8),因为该方法允许多个实现。

顺便说一句,如果您使用b'0'代替48,可能会更清楚。

答案 1 :(得分:4)

如果性能很重要,请考虑使用有助于编译器生成 SIMD 指令的实现。

例如,对于 f32,使用 16 个通道(总共 512 位):

use std::convert::TryInto;

const LANES: usize = 16;

pub fn nonsimd_sum(values: &[f32]) -> f32 {
    let chunks = values.chunks_exact(LANES);
    let remainder = chunks.remainder();

    let sum = chunks.fold([0.0f32; LANES], |mut acc, chunk| {
        let chunk: [f32; LANES] = chunk.try_into().unwrap();
        for i in 0..LANES {
            acc[i] += chunk[i];
        }
        acc
    });

    let remainder: f32 = remainder.iter().copied().sum();

    let mut reduced = 0.0f32;
    for i in 0..LANES {
        reduced += sum[i];
    }
    reduced + remainder
}

pub fn naive_sum(values: &[f32]) -> f32 {
    values.iter().sum()
}

为了

let values = (0..513).map(|x| x as f32).collect::<Vec<_>>();

以上比我电脑上的 values.iter().sum() 快 10 倍:

nonsimd_sum             time:   [77.341 ns 77.773 ns 78.378 ns]
naive_sum               time:   [739.97 ns 740.48 ns 740.97 ns]

并且比使用 packed_simd2 慢约 10%(但它不需要每晚使用)。