为什么一个包含100亿次迭代的大型for循环在Python中运行的时间要比在C中运行的时间长?

use*_*627 7 c python python-3.x

我目前正在比较Python3和C中的两个循环计算.对于Python,我有:

# Python3
t1 = time.process_time()
a = 100234555
b = 22333335
c = 341500
for i in range(1, 10000000001):
    a = a - (b % 2)
    b = b - (c % 2)
print("Sum is", a+b)
t2 = time.process_time()
print(t2-t1, "Seconds")
Run Code Online (Sandbox Code Playgroud)

然后在C中,我做同样的事情:

#include <stdio.h>

int main() {
   long long a = 100234555;
   long long b = 22333335;  
   long long c = 341500;
   for(long long i = 1; i <= 10000000000; i++){
        a = a - (b % 2);
        b = b - (c % 2);
   }
   printf("Sum is %lld\n", a+b);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在Python和C中对代码进行了定时.Py的时间约为3500秒,而C中的时序(包括编译和执行)仅需0.3秒左右.

我想知道如何在时间上有这么大的差异.执行是在具有100 GB Ram和足够处理能力的服务器上完成的.

wiz*_*zz4 15

部分原因是Python字节代码由程序而不是CPU直接执行,但大部分开销是由整数的不变性引起的内存分配和释放造成的,这是由于对象模型而不是interpretedness.

发生的事情是你的C代码可以改变数字的值,但是Python数字是不可变的,这意味着它们不会改变.这意味着当你做一笔总和时,Python必须int为每个新值创建一个新对象,然后int在它们不再使用后销毁它们.这使得它比仅修改单个内存值慢得多.


你的C编译器也有可能是聪明的,并且通过一系列优化它可以完全删除你的for循环的原因,结果将是相同的 - 就好像循环实际运行一样.我希望代码的运行速度比你的例子中的情况要快得多,但它可以做到这一点.

Python没有这样的智能编译器.它不能做那么大而聪明的事情; 它只是不是为了优化代码而设计的,因为在动态类型语言中这么做是如此困难(尽管Python强类型的事实确实使它有点可能.

  • 这是真的吗?使用对象类型而不是整数的纯值,没有机制来优化对象,当它们没用时?为什么??? (2认同)

chq*_*lie 8

正如dmuir注意到的,如果编译器正确地传播一些常量,代码可以大大简化.例如:clang -O1将C代码编译为此(cf https://gcc.godbolt.org/z/1ZH8Rm):

main:                                   # @main
        push    rax
        movabs  rsi, -9877432110
        mov     edi, offset .L.str
        xor     eax, eax
        call    printf
        xor     eax, eax
        pop     rcx
        ret
.L.str:
        .asciz  "Sum is %lld\n"
Run Code Online (Sandbox Code Playgroud)

gcc -O1 产生基本相似的代码.

由于这归结为一次调用printf,解释似乎是:

  • Python编译器不像C编译器那样智能优化此代码.
  • 你的C编译器需要很长时间来编译这12行代码.考虑到硬件设置,3秒太长了!我的dinky笔记本电脑只需0.15秒即可编译并运行所有优化代码.你在编译为C++吗?

使用optimisations disabled(-O0)测试C版本会产生以下输出:

$ time (clang -O0 -o loop10g loop10g.c && ./loop10g)
Sum is -9877432110

real    4m15.352s
user    3m47.232s
sys     0m3.252s
Run Code Online (Sandbox Code Playgroud)

未经优化的C比Python更快:255秒vs:3500

Python代码使用字节代码和具有动态类型值的堆栈进行解释:10到20的因子是典型的减速.此外,整数运算自动切换到bignum模式以获得较大的值,这可能是这里的情况,尽管惩罚应该更高.