为什么在这种情况下Python比C慢得多?

4

我正在解决一些项目欧拉问题,为问题10编写了相同的函数...

令我惊奇的是,C语言解决方案运行约4秒钟,而Python解决方案需要约283秒钟。我很难向自己解释为什么C实现比Python实现快那么多,到底发生了什么?

C:

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

int is_prime(int num)
{
    int sqrtDiv = lround(sqrt(num));
    while (sqrtDiv > 1) {
        if (num % sqrtDiv == 0) {
            return(0);
        } else {
            sqrtDiv--;
        }
    }
    return(1);
}

int main () 
{
    clock_t start = clock();

    long sum = 0;
    for ( int i = 2; i < 2000000; i++ ) {
        if (is_prime(i)) {
            sum += i;
        }
    }
    printf("Sum of primes below 2,000,000 is: %ld\n", sum);

    clock_t end = clock();
    double time_elapsed_in_seconds = (end - start)/(double)CLOCKS_PER_SEC;
    printf("Finished in %f seconds.\n", time_elapsed_in_seconds);   
}

Python:

from math import sqrt
import time


def is_prime(num):
    div = round(sqrt(num))
    while div > 1:
        if num % div == 0:
            return False
        div -= 1
    return True

start_time = time.clock()

tsum = 0
for i in range(2, 2000000):
    if is_prime(i):
        tsum += i

print tsum
print('finished in:', time.clock() - start_time, 'seconds')

10
如果你使用的是Python 2.7,range(2, 2000000) 实际上会在内存中构建一个包含大约2000000个整数的列表。在C语言中,你没有做同样等价的事情。请尝试使用xrange(),或切换到Python 3,在Python 3中,range()是一个惰性迭代器。 - Akshat Mahajan
静态类型声明,可能使用内存效率低下的迭代器或 Python 中的生成器。 - Dan
1
div 在你的 Python 代码中是浮点数,但 sqrtDiv 在你的 C 代码中是整数。 - Paul Hankin
@PaulHankin 在测试了一个 xrange() 版本之后,我不得不同意。 - Akshat Mahajan
2
修复我上面提到的int/float错误后,Python版本比C版本慢了大约21倍。对于处理大量小整数求和代码来说,这个速度差距大致在合理范围内。 - Paul Hankin
显示剩余9条评论
1个回答

2
在这种情况下,是CPython(实现方式)比Python慢。CPython需要解释字节码,这几乎总是比编译的C代码慢。它所做的工作比等效的C代码更多。理论上,每次调用sqrt都需要查找该函数,而不仅仅是调用已知地址。
如果您想从Python获得可比较的速度,可以使用类型注释并使用Cython编译源代码,或尝试使用Pypy进行一些JIT性能优化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接