rust - 如何在 Rust 中为 Criterion 基准创建随机输入
问题描述
我正在尝试annotate
使用 Criterion 基准测试库对例程进行基准测试。该例程正在检查一个&[&str]
参数(2D 方字符串)并返回Vec<String>
,我怀疑它的执行时间可能取决于参数的内容。因此,我想随机化单个工作负载的输入,在这种情况下,工作负载意味着字符串参数的宽度和高度(通常是宽度 == 高度)。
我注意到 Criterion 具有采用两个闭包而不是单个定时闭包、一个 Setup 和一个 Routine(定时)的方法iter_batched
。iter_batched_ref
它们都是 FnMut 所以所有捕获的变量都是可变引用(据我所知)。因此,我尝试Vec<Vec<u8>>
在常规仅调用我的annotate
函数时随机化设置中 a 的内容。
fn plant_mines<R: Rng + ?Sized>(mfield: &mut Vec<Vec<u8>>, rng: &mut R) {
mfield.into_iter().flatten().for_each(|x| *x = if rng.gen::<f32>() < MINE_RATE {MINE} else {EMPTY});
}
pub fn benchmark(c: &mut Criterion) {
let mut rng = rand_pcg::Pcg64Mcg::seed_from_u64(RAND_SEED);
let bench_params : [(usize, usize); 4] = [
(3, 3),
(5, 5),
(8, 8),
(16, 16)
];
let dims2str = |d : (usize, usize)| { let (w, h) = d; format!("{:}, {:}", w, h) };
let mut group = c.benchmark_group("Minefield Benchmark");
for dims in bench_params.iter() {
group.bench_with_input(BenchmarkId::from_parameter(dims2str(*dims)), dims, |b, (w, h)| {
let mut mf : Vec<Vec<u8>> = (0..*h).map(|_| iter::repeat(EMPTY).take(*w).collect::<Vec<_>>()).collect();
let mf_ref = mf.iter().map(|vu8| str::from_utf8(&vu8).unwrap()).collect::<Vec<&str>>();
b.iter_batched(|| {
plant_mines(&mut mf, &mut rng);
}, |_| annotate(&mf_ref), BatchSize::SmallInput);
});
}
group.finish();
}
通常,设置函数应该为要使用的例程生成输入,但在这种情况下,我省略了它们。mf_ref
持有一个参考向量,Vec<Vec<u8>>
我不想在定时例程中创建/分配这个向量,否则,它将为基准测试产生更多噪音。不幸的是,借阅检查员并不高兴。
我试图在 Setup 闭包中创建输入向量,但它无法将参考向量返回到定时例程。我试图了解 或 中的任何一个是否Cell
可以RefCell
解决问题,但我无法掌握足够的知识来在这里申请(如果可能的话)。这Cell
是不可能的,因为Vec
没有实现Copy
我理解的特征。
如何在仅对annotate
函数进行基准测试并为每批样本使用随机输入的同时满足编译器的要求?
解决方案
您没有按预期使用批处理机制,这样做将解决您的冲突借用问题。mf_ref
您应该在 setup 闭包中创建mf
并返回它,而不是关闭基准例程。这样,就不会共享对mf
.
b.iter_batched(|| {
let mut mf : Vec<Vec<u8>> = (0..*h).map(|_| iter::repeat(EMPTY).take(*w).collect::<Vec<_>>()).collect();
plant_mines(&mut mf, &mut rng);
mf
}, |mf| annotate(&mf), BatchSize::SmallInput);
请注意,这也摆脱了mf_ref
' 转换为&str
. &'static str
除非字符串全部都是(如果它们始终是对应于 MINE 或 EMPTY 的字符串,那么您可以只有两个对应的字符串文字,这可能会在此处实现(容易) );您需要重新设计您的annotate
,以便它适用于拥有的结构或仅引用&'static str
s 的结构。(或者你可以把它放在 旁边的基准闭包中annotate
,但是你正在测量它。)
当然,您不应该仅仅为了基准而重塑您的代码,但这可能会给您在其他地方的灵活性,因为长期引用通常不方便。我不能确切地告诉你该怎么做,因为我不知道and的annotate
作用或价值是什么。MINE
EMPTY
推荐阅读
- python - Pandas:使用另一个表的“虚拟变量”创建一个表
- angular - 使用与当前路线相关的路线参数导航到子路线 - Angular 8
- c++ - 为什么一个向量上的多线程操作很慢?
- c++ - 通过 ccmake 在 cmake 中缓存依赖选项
- python - Python 错误:字节流后无法找到“endstream”标记
- typescript - 获取每个数组的一项并检查两者的条件
- scala - 在 scala 中创建的图像看起来不像预期的那样。不知道为什么
- java - 如何使用随机化为循环中的单个迭代指定不同的对象参数?
- visual-studio - Visual Studio 2019 中有没有办法导航到项目文件中没有的标头?
- git - 使用分支或单独存储库来维护不向后兼容的多个代码版本的正确方法是什么?