为什么 Python 集合交集比 Rust HashSet 交集更快?

2024-04-05

这是我的Python代码:

len_sums = 0
for i in xrange(100000):
    set_1 = set(xrange(1000))
    set_2 = set(xrange(500, 1500))
    intersection_len = len(set_1.intersection(set_2))
    len_sums += intersection_len
print len_sums

这是我的 Rust 代码:

use std::collections::HashSet;

fn main() {
    let mut len_sums = 0;
    for _ in 0..100000 {
        let set_1: HashSet<i32> = (0..1000).collect();
        let set_2: HashSet<i32> = (500..1500).collect();
        let intersection_len = set_1.intersection(&set_2).count();
        len_sums += intersection_len;
    }
    println!("{}", len_sums);
}

我相信这些大致相当。我得到以下性能结果:

time python set_performance.py
50000000

real    0m11.757s
user    0m11.736s
sys 0m0.012s

and

rustc set_performance.rs -O       
time ./set_performance 50000000

real    0m17.580s
user    0m17.533s
sys 0m0.032s

建筑与cargo and --release给出相同的结果。

我意识到Python的set是用C实现的,所以预计会很快,但没想到比Rust还快。难道它不需要进行 Rust 不需要的额外类型检查吗?

也许我在编译 Rust 程序的方式中遗漏了一些东西,是否还有我应该使用的其他优化标志?

另一种可能性是代码并不真正等效,Rust 正在做不必要的额外工作,我是否遗漏了什么?

Python版本:

In [3]: import sys

In [4]: sys.version
Out[4]: '2.7.6 (default, Jun 22 2015, 17:58:13) \n[GCC 4.8.2]'

锈版

$ rustc --version
rustc 1.5.0 (3d7cd77e4 2015-12-04)

我使用的是 Ubuntu 14.04,我的系统架构是 x86_64。


当我将集合构建移出循环并仅重复交集时,对于这两种情况,Rust 当然都比 Python 2.7 更快。

我只读过Python 3(设置对象.c) https://github.com/python/cpython/blob/master/Objects/setobject.c#L1274,但是 Python 的实现有一些优点。

它利用了两个 Python set 对象使用相同哈希函数的事实,因此它不会重新计算哈希。锈HashSet它们的散列函数具有实例唯一的键,因此在交集期间,它们必须将一组中的键与另一组的散列函数重新进行散列。

另一方面,Python 必须调用动态键比较函数,例如PyObject_RichCompareBool对于每个匹配的哈希,而 Rust 代码使用泛型并将专门化哈希函数和比较代码i32。哈希的代码i32Rust 看起来相对便宜,并且删除了大部分哈希算法(处理超过 4 字节的输入)。


看来是布景的构造setsPython 和 Rust 不同。事实上,不仅仅是构建,还有一些重要的代码正在运行来破坏 RustHashSet也是如此。 (这可以改进,在这里提交错误:#31711 https://github.com/rust-lang/rust/issues/31711)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Python 集合交集比 Rust HashSet 交集更快? 的相关文章

随机推荐