我想学习一些关于Rust 任务的知识,所以我做了一个蒙特卡罗计算

以下是C版本:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

#define PI 3.1415926535897932

double monte_carlo_pi(int nparts)
{
    int i, in=0;
    double x, y;
    srand(getpid());

    for (i=0; i<nparts; i++) {
        x = (double)rand()/(double)RAND_MAX;
        y = (double)rand()/(double)RAND_MAX;

            if (x*x + y*y < 1.0) {
            in++;
        }
    }

    return in/(double)nparts * 4.0;
}

int main(int argc, char **argv)
{
    int nparts;
    double mc_pi;

    nparts = atoi(argv[1]);
    mc_pi = monte_carlo_pi(nparts);
    printf("computed: %f error: %f\n", mc_pi, mc_pi - PI);
}

Rust版本不是逐行端口:

use std::rand;
use std::rand::distributions::{IndependentSample,Range};

fn monte_carlo_pi(nparts: uint ) -> uint {
    let between = Range::new(0f64,1f64);
    let mut rng = rand::task_rng();
    let mut in_circle = 0u;
    for _ in range(0u, nparts) {
        let a = between.ind_sample(&mut rng);
    let b = between.ind_sample(&mut rng);

    if a*a + b*b <= 1.0 {
        in_circle += 1;
    }
    }
    in_circle
}

fn main() {
    let (tx, rx) = channel();

    let ntasks = 4u;
    let nparts = 100000000u; /* I haven't learned how to parse cmnd line args yet!*/
    for _ in range(0u, ntasks) {
        let child_tx = tx.clone();
        spawn(proc() {
        child_tx.send(monte_carlo_pi(nparts/ntasks));
        });
    }

    let result = rx.recv() + rx.recv() + rx.recv() + rx.recv();

    println!("pi is {}", (result as f64)/(nparts as f64)*4.0);
}

构建C版本并计时:

$ clang -O2 mc-pi.c -o mc-pi-c; time ./mc-pi-c 100000000
computed: 3.141700 error: 0.000108
./mc-pi-c 100000000  1.68s user 0.00s system 99% cpu 1.683 total

构建Rust 版本并计时:

$ rustc -v      
rustc 0.12.0-nightly (740905042 2014-09-29 23:52:21 +0000)
$ rustc --opt-level 2 --debuginfo 0 mc-pi.rs -o mc-pi-rust; time ./mc-pi-rust  
pi is 3.141327
./mc-pi-rust  2.40s user 24.56s system 352% cpu 7.654 tota

推荐答案

正如多伯特所观察到的,瓶颈是随机数发生器.这里有一个是快速的,在每个线程上的种子不同

fn monte_carlo_pi(id: u32, nparts: uint ) -> uint {
    ...
    let mut rng: XorShiftRng = SeedableRng::from_seed([id,id,id,id]);
    ...
}

Rust相关问答推荐

如何在不安全的代码中初始化枚举 struct

borrow 和内部IntoIterator

使用pyo3::Types::PyIterator的无限内存使用量

在函数内定义impl和在函数外定义impl的区别

如何仅使用http机箱发送http请求?

制作一片连续整数的惯用Rust 方法?

如何从ruust中的fig.toml中读取?

JSON5中的变量类型(serde)

AXUM一路由多个不包括URL的参数类型

如何初始化选项<;T>;数组Rust 了?

为什么rustc会自动降级其版本?

Cargo.toml:如何有条件地启用依赖项功能?

具有多个键的 HashMap

为什么 js_sys Promise::new 需要 FnMut?

仅发布工作区的二进制 crate

为什么某些类型参数仅在特征边界中使用的代码在没有 PhantomData 的情况下进行编译?

‘&T as *const T as *mut T’ 在 ‘static mut’ 项目中合适吗?

(let b = MyBox(5 as *const u8); &b; ) 和 (let b = &MyBox(5 as *const u8); ) 之间有什么区别

匹配结果时的简洁日志(log)记录

如何从 many0 传播 Nom 失败上下文?