我在使用这段代码时遇到了奇怪的性能特征,具体取决于我如何运行它:
use std::time::Instant;
fn main() {
let start_time = Instant::now();
for p in 1..10000000 {
if prime_check(p as f64) {
println!("{} is prime", p);
}
}
let end_time = Instant::now();
let elapsed_time = end_time - start_time;
println!("Elapsed time: {:?}", elapsed_time);
}
fn prime_check(p: f64) -> bool {
let k: u64 = p.sqrt() as u64;
for j in 2..=k {
if p % j as f64 == 0.0 {
return false;
}
}
true
}
当我使用 Rust 插件在 PyCharm 中按 Alt+Shift+F10 时,我得到:
9999943 is prime
9999971 is prime
9999973 is prime
9999991 is prime
Elapsed time: 11.537594s
当我使用 rustc 构建并运行可执行文件时,我得到以下信息:
PS C:\Users\User\Desktop\Proj\Rs\src> rustc -O main.rs
9999943 is prime
9999971 is prime
9999973 is prime
9999991 is prime
Elapsed time: 37.1560723s
我尝试将其添加到
Cargo.toml
,但没有什么区别:
[profile.dev]
opt-level = 3
如何使 rustc 生成的可执行文件像 PyCharm 一样快?是什么造成了这样的差异?
对我来说,你的代码运行在:
cargo run
:Elapsed time: 267.3377065s
cargo run --release
:Elapsed time: 212.5371301s
现在让我们在没有
println
的情况下再次运行它,因为我怀疑这些是代码缓慢的主要原因。事实上,您的代码在 PowerShell 和 PyCharm 中执行不同的事实是因为它们的 println
处理不同。
use std::time::Instant;
fn main() {
let start_time = Instant::now();
let mut count: u64 = 0;
for p in 1..10000000 {
if prime_check(p as f64) {
count += 1;
}
}
let end_time = Instant::now();
let elapsed_time = end_time - start_time;
println!("Found {} primes.", count);
println!("Elapsed time: {:?}", elapsed_time);
}
fn prime_check(p: f64) -> bool {
let k: u64 = p.sqrt() as u64;
for j in 2..=k {
if p % j as f64 == 0.0 {
return false;
}
}
true
}
cargo run
:
Found 664580 primes.
Elapsed time: 54.3782759s
cargo run --release
:
Found 664580 primes.
Elapsed time: 30.7077071s
我怀疑此代码的输出现在将在 PowerShell 和 PyCharm 中执行类似的操作。
作为进一步的评论,我想提一下,您对
prime_check
的实现是危险的 - 使用 f64
会在某个点引入舍入错误,并且会产生不正确的结果。
使用
u64
代替:
use std::time::Instant;
fn main() {
let start_time = Instant::now();
let mut count: u64 = 0;
for p in 1..10000000 {
if prime_check(p) {
count += 1;
}
}
let end_time = Instant::now();
let elapsed_time = end_time - start_time;
println!("Found {} primes.", count);
println!("Elapsed time: {:?}", elapsed_time);
}
fn prime_check(p: u64) -> bool {
let k: u64 = (p as f64).sqrt() as u64;
for j in 2..=k {
if p % j == 0 {
return false;
}
}
true
}
Found 664580 primes.
Elapsed time: 9.4109272s