我目前正在比较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")
然后在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;
}
我在Python和C中都对代码计时。Python的时间约为3500秒,而C(包括编译和执行)的时间仅约0.3秒。
我想知道时间安排有多么大的差异。该执行是在具有100 GB Ram和足够处理能力的服务器上完成的。
答案 0 :(得分:15)
部分原因是Python字节码是由程序而不是直接由CPU执行的,但是大部分开销是由于整数的不可变性而导致的内存分配和释放,这是由于对象模型引起的,而不是解释性。
这是怎么回事,您的C代码可以更改数字的值,但是在Python中数字是不可变的,这意味着它们不会更改。这意味着在进行求和时,Python必须为每个新值创建一个新的int
对象,然后在不再使用旧的int
之后销毁它们。这比仅修改单个内存值要慢得多。
您的C编译器也可能很聪明,原因是通过一连串的优化,它可以完全删除您的for
循环,结果将是相同的-就像循环实际上在运行一样。我希望代码的运行速度比示例中的运行速度要快得多,但是它可以做到。
Python没有这样的智能编译器。它不能做那么宏伟的事情。它并不是为了优化代码而设计的,因为在动态类型的语言中很难可靠地做到这一点(尽管Python是强类型的事实确实使它具有某种可能性。
答案 1 :(得分:8)
正如dmuir所注意到的,如果编译器正确传播某些常量,则可以大大简化代码。例如:struct
将C代码编译为此(cf https://gcc.godbolt.org/z/1ZH8Rm):
clang -O1
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"
产生基本上相似的代码。
由于这归结为对gcc -O1
的单个调用,因此解释似乎是:
在禁用优化功能(printf
)的情况下测试C版本会产生以下输出:
-O0
未优化的C仍然比Python快得多:255秒vs:> 3500
Python代码使用字节码和具有动态类型值的堆栈来解释:典型的减速是10到20。此外,对于较大的值,整数算法会自动切换到bignum模式,在这种情况下可能会发生这种情况,尽管代价会更高。
答案 2 :(得分:0)
答案很简单。 Python是解释性语言。所有指令均由解释器(执行脚本的特殊程序)执行。它比编译为本机代码的C代码要慢得多。