我阅读了100,并在Rust年重写了作者的"幼稚"实现.C++变体是:

#include <utility>
#include <cstdio>
#include <cstdlib>

std::pair<int, int> pointsA[1000001];
std::pair<int, int> pointsB[1000001];

int main() {
    int n, t;
    unsigned long long dist;

    scanf("%d", &t);

    while(t-->0) {
        dist = 4000000000LL;
        scanf("%d", &n);

        for(int i = 0; i < n; i++) {
            scanf("%d%d", &pointsA[i].first, &pointsA[i].second);
        }

        for(int i = 0; i < n; i++) {
            scanf("%d%d", &pointsB[i].first, &pointsB[i].second);
        }

        for(int i = 0; i < n ;i++) {
            for(int j = 0; j < n ; j++) {
                if(abs(pointsA[i].first - pointsB[j].first) + abs(pointsA[i].second - pointsB[j].second) < dist)
                    dist = abs(pointsA[i].first - pointsB[j].first) + abs(pointsA[i].second - pointsB[j].second);
            }
        }
        printf("%lld\n", dist);
    }
}

Rust 变种是:

use std::io;
use std::io::BufReader;
use std::io::BufRead;

fn read_array(stdin: &mut BufReader<io::Stdin>, array_len: usize, points: &mut Vec<(i32, i32)>) {
    let mut line = String::new();
    for _ in 0..array_len {
        line.clear();
        stdin.read_line(&mut line).unwrap();
        let mut item = line.split_whitespace();
        let x = item.next().unwrap().parse().unwrap();
        let y = item.next().unwrap().parse().unwrap();
        points.push((x, y));
    }
}

fn manhattan_dist(a: &(i32, i32), b: &(i32, i32)) -> u32 {
    ((a.0 - b.0).abs() + (a.1 - b.1).abs()) as u32
}

fn main() {
    let mut line = String::new();
    let mut stdin = BufReader::new(io::stdin());
    stdin.read_line(&mut line).unwrap();
    let n_iters = line.trim_right().parse::<usize>().unwrap();
    let mut points_a = Vec::with_capacity(10000);
    let mut points_b = Vec::with_capacity(10000);
    for _ in 0..n_iters {
        line.clear();
        stdin.read_line(&mut line).unwrap();
        let set_len = line.trim_right().parse::<usize>().unwrap();
        points_a.clear();
        points_b.clear();
        read_array(&mut stdin, set_len, &mut points_a);
        read_array(&mut stdin, set_len, &mut points_b);
        let mut dist = u32::max_value();
        for i in points_a.iter() {
            for j in points_b.iter() {
                dist = std::cmp::min(manhattan_dist(i, j), dist);
            }
        }
        println!("{}", dist);
    }
}

然后,我用Python脚本生成了数据:

import random

ITER = 100
N = 10000
MAX_INT = 1000000

print("%d" % ITER)

for _ in range(0, ITER):
    print("%d" % N)
    for _ in range(0, N):
        print(random.randrange(-MAX_INT, MAX_INT + 1), random.randrange(1, MAX_INT + 1))
    for _ in range(0, N):
        print(random.randrange(-MAX_INT, MAX_INT + 1), random.randrange(-MAX_INT, 0))

并分别用g++ -Ofast -march=nativerustc -C opt-level=3编译了这两个变量.时间安排如下:

C++

real    0m7.789s
user    0m7.760s
sys     0m0.020s

Rust

real    0m28.589s
user    0m28.570s
sys     0m0.010s

为什么我的 rust 代码比C++变量慢四倍?我使用的是Rust 1.12.0-beta.1.

我增加了时间测量:

let now = SystemTime::now();
line.clear();
stdin.read_line(&mut line).unwrap();
let set_len = line.trim_right().parse::<usize>().unwrap();
points_a.clear();
points_b.clear();
read_array(&mut stdin, set_len, &mut points_a);
read_array(&mut stdin, set_len, &mut points_b);
io_time += now.elapsed().unwrap();

let now = SystemTime::now();
let mut dist = u32::max_value();
for i in points_a.iter() {
    for j in points_b.iter() {
        dist = std::cmp::min(manhattan_dist(i, j), dist);
    }
}
calc_time += now.elapsed().unwrap();

writeln!(&mut std::io::stderr(), "io_time: {}, calc_time: {}", io_time.as_secs(), calc_time.as_secs()).unwrap();张照片io_time: 0, calc_time: 27张.

我试过每晚rustc 1.13.0-nightly (e9bc1bac8 2016-08-24)次:

$ time ./test_rust < data.txt  > test3_res
io_time: 0, calc_time: 19

real    0m19.592s
user    0m19.560s
sys     0m0.020s
$ time ./test1 < data.txt  > test1_res

real    0m7.797s
user    0m7.780s
sys     0m0.010s

因此,现在我的Core i7米差距约为2.7倍.

推荐答案

区别当然是-march=native...有点Rust的速度可以达到-C target_cpu=native,但这并不能带来同样的速度优势.这是因为LLVM不愿意在这种情况下矢量化,而GCC不愿意.您可以注意到,使用Clang,也使用LLVM的C++编译器也产生相对缓慢的代码.

为了鼓励LLVM进行矢量化,可以将主循环移动到单独的函数中.或者,可以使用本地块.如果你仔细编写代码

let dist = {
    let mut dist = i32::max_value();
    for &(a, b) in &points_a[..n] {
        for &(c, d) in &points_b[..n] {
            dist = std::cmp::min(((a - c).abs() + (b - d).abs()), dist);
        }
    }
    dist
} as u32;

Rust与C++的差值接近可忽略(4%).

Rust相关问答推荐

通用池类型xsx

Rust&;Tokio:如何处理更多的信号,而不仅仅是SIGINT,即SIGQUE?

不能在一个代码分支中具有不变的自身borrow ,而在另一个代码分支中具有可变的self borrow

当发送方分配给静态时,Tokio MPSC关闭通道

Rust面向对象设计模式

有没有一种方法可以创建一个闭包来计算Rust中具有随机系数的n次多项式?

具有多个键的 HashMap

Rust中的位移操作对范围有什么影响?

Rust 中的 Option as_ref 和 as_deref 有什么不同

如何从 rust 中的同一父目录导入文件

Rust 中的自动取消引用是如何工作的?

在给定 Rust 谓词的情况下,将 Some 转换为 None 的惯用方法是什么?

std::vector::shrink_to_fit 如何在 Rust 中工作?

如何使用泛型满足 tokio 异步任务中的生命周期界限

使用自定义 struct 收集 Vec

是否可以在 Rust 中的特定字符上实现特征?

试图理解 Rust 中的可变闭包

当我在 struct 中存储异步函数时,为什么它需要生命周期

你能告诉我如何在 Rust 中使用定时器吗?

Rust 中的运行时插件