编者注:这个问题的例子来自于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);
}
答案 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%(但它不需要每晚使用)。