为什么我的 u64 Rust 程序使用 Docker(桌面)比本地 macOS 可执行文件运行得更快?

问题描述 投票:0回答:1

这是一个用 Rust 编写的简单的 n 次素数程序。实施效率低下,但这不是重点。

use std::time::Instant;

fn main() {
    let n = 10_000;
    let now = Instant::now();
    let nth = nth_prime(n);
    let elapsed = now.elapsed().as_micros();
    println!("prime #{} = {}", n, nth);
    println!("elapsed = {} µs", elapsed);
}

fn nth_prime(n: u64) -> u64 {
    let mut count = 1;
    let mut num = 2;
    while count < n {
        num += 1;
        if is_prime(num) {
            count += 1;
        }
    }
    num
}

fn is_prime(num: u64) -> bool {
    for i in 2..num {
        if num % i == 0 {
            return false;
        }
    }
    true
}

如果我使用

cargo run --release
在 macOS 上本地运行此程序,我会得到约 3.4 秒的一致执行时间。但是,如果我使用 Docker Desktop(在同一台笔记本电脑上)运行该程序,我会得到约 1.7 秒的一致执行时间。这是我正在使用的 Dockerfile:

FROM rust:1.50
WORKDIR /usr/src/playground
COPY Cargo.toml .
COPY Cargo.lock .
COPY src src
RUN cargo build --release
CMD cargo run --release

但是,如果我将所有

u64
切换为
u32
,则本机可执行文件在约 1.5 秒内一致运行,而 Docker 版本在约 1.6 秒内一致运行。

Linux 可执行文件是否以 macOS 可执行文件未优化的方式进行了优化?

请注意,我在 macOS Big Sur 版本 11.2.2 和 macOS Catalina 版本 10.15.17 上得到了相同的行为。我在两台笔记本电脑上使用 Docker Desktop 版本 3.1.0 和 Engine 版本 20.10.2,并且在两台笔记本电脑上使用 Cargo 版本 1.50.0。

另请注意,我在 Ubuntu 18.04 桌面上尝试了相同的基准测试。对于

cargo run --release
程序,本机 Linux 可执行文件 (
docker run
) 和 Docker 版本 (
u64
) 在约 1.02 秒内一致运行。

谢谢!

macos docker rust
1个回答
3
投票

MacOS 并不真正运行 docker,因此在运行 docker 时,您还运行一个 Linux 虚拟机来托管 docker 容器。该虚拟机可能正在使用 stable-x86_64-unknown-linux-gnu (因为这是 docker 镜像所期望的),而您的本机主机是其他目标。

您可以运行

rustup show
来查看本机主机上的活动工具链。我的猜测是,它可能是一个相当通用的 mac 工具链,与广泛的硬件兼容,而您的实际 mac 可能相当现代,因此您的硬件可能支持 LLVM 优化器(生锈的编译器后端)的一系列优化使用)不要“不敢”为您启用。

也许在发布模式下再次构建之前设置

RUSTFLAGS="-C target-cpu=native"
会带来性能提升?或者也许以某种方式运行一个完全不同的目标?

那么,主要问题:您编译的目标是什么,以及您在什么实际硬件上运行?

附录:这个问题很久以前就被问过。也许 rust 1.50 中使用的 LLVM 不太擅长针对 mac 进行优化,只需更新到当前的 rust 版本,事情就会变得更好?

© www.soinside.com 2019 - 2024. All rights reserved.