在这篇文章中,我们将创建一个能执行的Rust脚本来测量CPU的性能。
为了实现目标,我们将创建一些在循环中运行的虚拟计算,分布在所有可用的CPU 内核上。理想情况下,我们的计算需要CPU密集型任务,所以我们尽可能接近100%的CPU使用率。
创建一个Rust项目:
cargo new cpu-benchmark
在Cargo.toml文件中添加如下代码:
[dependencies]
indicatif = "0.17.5"
sysinfo = "0.29.7"
[profile.release]
lto = "fat"
strip = "debuginfo"
因为计算阶乘是一项cpu密集型任务,所以我们首先在src/main.rs文件中写入一个计算阶乘的函数:
pub fn factorial(num: u128) -> u128 {
(1..=num).product()
}
然后,我们在循环中调用这个阶乘函数:
fn add_one_loop(&n_loops: &u64) {
for _in in 0..n_loops {
let _ = factorial(20);
}
}
在main函数中,我们需要做一些处理:
对于系统信息,我们使用一个名为sysinfo的crate:
use sysinfo::{System, SystemExt};
fn main() {
let mut sys = System::new_all();
sys.refresh_all();
// 显示系统信息
println!("System name: {:?}", sys.name());
println!("System kernel version: {:?}", sys.kernel_version());
println!("System OS version: {:?}", sys.os_version());
println!("System host name: {:?}", sys.host_name());
// 获取CPU数
println!("Number of available threads: {}", sys.cpus().len());
}
进度条我们使用另一个名为indicatif的crate,此外,我们还测量开始和结束之间的时间,并计算每秒的计算次数以获得分数。
main.rs的完整代码如下:
use std::{thread::available_parallelism, time::Instant, env};
use indicatif::ProgressBar;
use sysinfo::{System, SystemExt};
pub fn factorial(num: u128) -> u128 {
(1..=num).product()
}
fn add_one_loop(&n_loops: &u64) {
for _in in 0..n_loops {
let _ = factorial(20);
}
}
fn main() {
let args: Vec<String> = env::args().collect();
let num_calcs_arg: Option<&String> = args.get(1);
let num_calcs: u64 = match num_calcs_arg {
Some(num_calcs_arg) => num_calcs_arg.trim().parse::<u64>().unwrap(),
None => 400000000,
};
let num_iters: u64 = 20000;
let total_calc: u64 = num_calcs * num_iters;
println!(
"Running {} calculations over {} iterations each with a total of {} calculations.",
&num_calcs, &num_iters, &total_calc,
);
// 获取系统信息
let mut sys = System::new_all();
sys.refresh_all();
// 显示系统信息
println!("System name: {:?}", sys.name());
println!("System kernel version: {:?}", sys.kernel_version());
println!("System OS version: {:?}", sys.os_version());
println!("System host name: {:?}", sys.host_name());
// 获取CPU数
println!("Number of available threads: {}", sys.cpus().len());
// 获取我们可以使用多少线程的信息,并使用其中的一半
let available_cores: u64 = available_parallelism().unwrap().get() as u64;
let iter_per_core: u64 = num_calcs / available_cores;
let now = Instant::now();
let bar = ProgressBar::new(num_iters);
for _i in 0..num_iters {
let mut results = Vec::new();
let mut threads = Vec::new();
for _i in 0..available_cores {
threads.push(std::thread::spawn(move || add_one_loop(&iter_per_core)));
}
for thread in threads {
results.extend(thread.join());
}
bar.inc(1);
}
bar.finish();
let elapsed = now.elapsed();
let calc_per_sec: f64 = (total_calc as f64) / (elapsed.as_secs() as f64);
println!("Total runtime: {:.2?}", elapsed);
println!("Calculations per second: {:.2?} seconds.", calc_per_sec);
}
现在运行如下命令测试我们的简单脚本:
cargo run --release
结果如下:
Running 400000000 calculations over 20000 iterations each with a total of 8000000000000 calculations.
System name: Some("Darwin")
System kernel version: Some("21.6.0")
System OS version: Some("12.6.6")
System host name: Some("master")
Number of available threads: 4
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 20000/20000
Total runtime: 2.52s
Calculations per second: 4000000000000.00 seconds.
我们获得了系统信息、运行时间、进度条和可解释的基准分数。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8