我编写了这个非常简单的 Rust 函数:
fn iterate(nums: &Box<[i32]>) -> i32 {
let mut total = 0;
let len = nums.len();
for i in 0..len {
if nums[i] > 0 {
total += nums[i];
} else {
total -= nums[i];
}
}
total
}
我编写了一个基本基准,它使用有序数组和随机数组调用该方法:
fn criterion_benchmark(c: &mut Criterion) {
const SIZE: i32 = 1024 * 1024;
let mut group = c.benchmark_group("Branch Prediction");
// setup benchmarking for an ordered array
let mut ordered_nums: Vec<i32> = vec![];
for i in 0..SIZE {
ordered_nums.push(i - SIZE/2);
}
let ordered_nums = ordered_nums.into_boxed_slice();
group.bench_function("ordered", |b| b.iter(|| iterate(&ordered_nums)));
// setup benchmarking for a shuffled array
let mut shuffled_nums: Vec<i32> = vec![];
for i in 0..SIZE {
shuffled_nums.push(i - SIZE/2);
}
let mut rng = thread_rng();
let mut shuffled_nums = shuffled_nums.into_boxed_slice();
shuffled_nums.shuffle(&mut rng);
group.bench_function("shuffled", |b| b.iter(|| iterate(&shuffled_nums)));
group.finish();
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
令我惊讶的是,这两个基准测试具有几乎完全相同的运行时间,而 Java 中的类似基准测试显示两者之间存在明显差异,这可能是由于在 shuffled 情况下分支预测失败所致。
我见过提到条件移动指令,但如果我otool -tv
是可执行文件(我在 Mac 上运行),我在iterate
方法输出中看不到任何内容。
谁能阐明为什么 Rust 中的有序和无序案例之间没有明显的性能差异?