我目前正在比较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和足够处理能力的服务器上完成的。
发布于 2018-09-29 16:20:40
这部分是因为Python字节码是由程序而不是直接由CPU执行的,但是大部分开销是由不可变的整数所引起的内存分配和去分配造成的,这是由于对象模型,而不是解释。
您的C代码可以更改数字的值,但在Python中,数字是不可变的,这意味着它们不会改变。这意味着当您完成和时,Python必须为每个新值创建一个新的int对象,然后在旧的int不再使用后销毁它们。这使得它比仅仅修改单个内存值要慢得多。
还有一种可能性,即您的C编译器是聪明的,以及通过一系列优化可以完全删除for循环的原因,结果将是相同的--就好像循环已经实际运行了一样。如果在您的示例中是这样的话,我希望代码的运行速度会比它快得多,但它可以做到这一点。
Python没有这样聪明的编译器。它不能做到这样的伟大和聪明的事情;它只是不是为了优化代码而设计的,因为在动态类型语言中这样做是很困难的(尽管Python是强类型的,这在某种程度上是有可能的)。
发布于 2018-09-29 21:43:51
正如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"gcc -O1产生本质上类似的代码。
由于这归结为对printf的单个调用,因此解释如下:
使用禁用的优化(-O0)测试C版本会产生以下输出:
$ time (clang -O0 -o loop10g loop10g.c && ./loop10g)
Sum is -9877432110
real 4m15.352s
user 3m47.232s
sys 0m3.252s使用未优化的C仍然比Python快得多: 255秒vs:>3500
Python代码使用字节代码和具有动态类型值的堆栈进行解释: 10到20的因子是典型的减速。此外,对于大值,整数算法会自动切换到bignum模式,这可能是这里的情况,尽管代价应该更高。
发布于 2018-09-29 16:16:26
答案很简单。Python是一种解释语言。所有指令都由解释器(执行脚本的特殊程序)执行。它比编译成本机代码的C代码慢得多。
https://stackoverflow.com/questions/52570192
复制相似问题