编者注:该问题的示例来自1.0之前的Rust版本,并引用了Rust中不再存在的类型和方法。答案仍然包含有价值的信息。
以下代码
let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum();
Run Code Online (Sandbox Code Playgroud)
导致以下错误:
let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum();
Run Code Online (Sandbox Code Playgroud)
对字节数组求和应该怎么做?
以下作品:
for byte in new_serial.as_bytes().iter() {
sum = sum + (byte - 48);
}
Run Code Online (Sandbox Code Playgroud)
Iterator::sum在Rust 1.11.0中已稳定。您可以从数组/ slice /中获得一个迭代器Vec,然后使用sum:
fn main() {
let a = [1, 2, 3, 4, 5];
let sum: u8 = a.iter().sum();
println!("the total sum is: {}", sum);
}
Run Code Online (Sandbox Code Playgroud)
特别要注意的是,sum: u8由于该方法允许多种实现,因此您需要指定要累加到()中的类型。请参阅为什么Rust无法推断出Iterator :: sum的结果类型?想要查询更多的信息。
应用于您的原始示例:
let new_serial = "01234";
let sum: u8 = new_serial.as_bytes().iter().map(|&x| x - 48).sum();
println!("{}", sum);
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果您使用b'0'而不是,可能会更清楚48。
如果性能很重要,请考虑使用有助于编译器生成 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()
}
Run Code Online (Sandbox Code Playgroud)
为了
let values = (0..513).map(|x| x as f32).collect::<Vec<_>>();
Run Code Online (Sandbox Code Playgroud)
以上比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]
Run Code Online (Sandbox Code Playgroud)
并且比使用慢约 10% packed_simd2(但它不需要每晚使用)。
| 归档时间: |
|
| 查看次数: |
3115 次 |
| 最近记录: |