计算1亿以内素数的个数,C/Rust/Python的性能差距有多大?测试结果出乎意料

C被公认为速度最快的编程语言,Rust的速度接近于C,二者差距在毫厘之间。如果单纯和C/Rust比速度的话,Python处于被碾压的地位,差不多慢了一个量级。不过,下面这个测试,却呈现了一个颠覆性的结果:使用相同的算法,分别用C语言、Rust语言和Python语言编程计算1亿以内素数的个数,三者用时之比为1:0.96:1.15!Rust居然比C快了一丢丢,而Python也不像是传说中的那么不堪,只比C慢了半个身位。差距是如此之小,三大语言几乎打了个平手。

测试任务 C平均耗时 Rust平均耗时 Python
计算1亿以内素数的个数 467.88毫秒 447.80毫秒 536.30毫秒

以下附上本次测试的C/Rust/Python代码,以便对该测试感兴趣的同学验证结论。我深知在这里讨论不同语言的性能是一个危险话题,故声明在先:本文无意褒贬任何一门编程语言,欢迎针对测试代码提出改进意见,若有非技术性意见,请免开尊口。

C代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int prime_sieve(int n) {
    
    
	int m = (int)sqrt((float)n) + 1;
	int total = 0;
	char *arr = (char *)malloc(n * sizeof(char));
	
	for (int i = 0; i < n; i++) {
    
    
		arr[i] = 1;
	}

	for (int i = 2; i < m; i++) {
    
    
		if (arr[i] > 0) {
    
    
			int j = 2 * i;
			while (j < n) {
    
    
				arr[j] = 0;
				j += i;
			}
		}
	}

	for (int i = 2; i < n; i++) {
    
    
		if (arr[i] > 0) {
    
    
			total += 1;
		}
	}

	return total;
}

int main() {
    
    
    clock_t start, finish;
	double duration;
	double time_sum = 0.0;

	for (int i = 0; i < 10; i++) {
    
    
		start = clock();
		int total = prime_sieve(100000000);
		finish = clock();
		duration = (double)(finish - start) * 1000.0 / CLOCKS_PER_SEC;
        time_sum += duration;

		printf("%d. 1亿以内的自然数中素数有%d个,耗时%f毫秒\n", i, total, duration);
	}

    printf("--------------------------------------------------\n");
    printf("C最终成绩:运行10次,平均耗时%f毫秒\n", time_sum/10.0);
 
    return 0;
}

编译开启O3优化,运行结果如下。

xufive@xuxiangwudeMacBook-Pro prime % gcc sieve.c -O3 -o sieve
xufive@xuxiangwudeMacBook-Pro prime % ./sieve                 
0. 1亿以内的自然数中素数有5761455个,耗时483.101000毫秒
1. 1亿以内的自然数中素数有5761455个,耗时467.608000毫秒
2. 1亿以内的自然数中素数有5761455个,耗时468.347000毫秒
3. 1亿以内的自然数中素数有5761455个,耗时467.092000毫秒
4. 1亿以内的自然数中素数有5761455个,耗时464.485000毫秒
5. 1亿以内的自然数中素数有5761455个,耗时455.552000毫秒
6. 1亿以内的自然数中素数有5761455个,耗时468.371000毫秒
7. 1亿以内的自然数中素数有5761455个,耗时466.685000毫秒
8. 1亿以内的自然数中素数有5761455个,耗时468.269000毫秒
9. 1亿以内的自然数中素数有5761455个,耗时469.323000毫秒
--------------------------------------------------
C最终成绩:运行10次,平均耗时467.883300毫秒

Rust代码

use std::time::Instant;

fn main() {
    
    
    let mut time_sum: u128 = 0;

    for i in 0..10 {
    
    
        let now = Instant::now();
        let total = prime_sieve(100_000_000);
        let duration = now.elapsed().as_millis();
        time_sum += duration;

        println!("{}. 1亿以内的自然数中素数有{}个,耗时{}毫秒", i, total, duration);
    }

    println!("--------------------------------------------------");
    println!("Rust最终成绩:运行10次,平均耗时{}毫秒", (time_sum as f64)/10.0);
}

fn prime_sieve(n: usize) -> usize {
    
    
    let m: usize = f64::sqrt(n as f64) as usize + 1;
    let mut total: usize = 0;
    let mut arr: Vec<u8> = [1].repeat(n);

    for i in 2..m {
    
    
        if arr[i] > 0 {
    
    
            let mut j: usize = 2 * i;
            while j < n {
    
    
                arr[j] = 0;
                j += i;
            }
        }
    }

    for i in 2..n {
    
    
        if arr[i] > 0 {
    
    
            total += 1;
        }
    }

    total
}

构建使用release参数,运行结果如下。

xufive@xuxiangwudeMacBook-Pro prime % cargo build --release
    Finished release [optimized] target(s) in 0.00s
xufive@xuxiangwudeMacBook-Pro prime % cd target/release 
xufive@xuxiangwudeMacBook-Pro release % ./prime 
0. 1亿以内的自然数中素数有5761455个,耗时430毫秒
1. 1亿以内的自然数中素数有5761455个,耗时448毫秒
2. 1亿以内的自然数中素数有5761455个,耗时452毫秒
3. 1亿以内的自然数中素数有5761455个,耗时447毫秒
4. 1亿以内的自然数中素数有5761455个,耗时449毫秒
5. 1亿以内的自然数中素数有5761455个,耗时453毫秒
6. 1亿以内的自然数中素数有5761455个,耗时447毫秒
7. 1亿以内的自然数中素数有5761455个,耗时449毫秒
8. 1亿以内的自然数中素数有5761455个,耗时451毫秒
9. 1亿以内的自然数中素数有5761455个,耗时452毫秒
--------------------------------------------------
Rust最终成绩:运行10次,平均耗时447.8毫秒

Python代码

import time
import numpy as np

def get_prime_num(n):
    """返回小于n的自然数中素数的个数"""
    
    m = int(np.sqrt(n)) + 1
    arr = np.ones(n, dtype=np.uint8)
    total = 0

    for i in range(2, m):
        if arr[i] > 0:
            arr[2*i::i] = 0

    return np.where(arr[2:] > 0)[0].shape[0]

if __name__ == '__main__':
    time_sum = 0
    for i in range(10):
        t0 = time.time()
        total = get_prime_num(100_000_000)
        dutation = round((time.time() - t0) * 1000)
        time_sum += dutation

        print('%d. 1亿以内的自然数中素数有%d个,耗时%d毫秒'%(i, total, dutation))
    
    print("--------------------------------------------------")
    print("Python最终成绩:运行10次,平均耗时%.3f毫秒" % (time_sum/10.0));

我的Python解释器版本为py3.11.2,运行结果如下。

xufive@xuxiangwudeMacBook-Pro prime % python3 prime.py
0. 1亿以内的自然数中素数有5761455个,耗时526毫秒
1. 1亿以内的自然数中素数有5761455个,耗时540毫秒
2. 1亿以内的自然数中素数有5761455个,耗时538毫秒
3. 1亿以内的自然数中素数有5761455个,耗时538毫秒
4. 1亿以内的自然数中素数有5761455个,耗时538毫秒
5. 1亿以内的自然数中素数有5761455个,耗时538毫秒
6. 1亿以内的自然数中素数有5761455个,耗时537毫秒
7. 1亿以内的自然数中素数有5761455个,耗时537毫秒
8. 1亿以内的自然数中素数有5761455个,耗时535毫秒
9. 1亿以内的自然数中素数有5761455个,耗时536毫秒
--------------------------------------------------
Python最终成绩:运行10次,平均耗时536.300毫秒

猜你喜欢

转载自blog.csdn.net/xufive/article/details/129880549
今日推荐