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强类型的事实确实使它有点可能.
正如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,解释似乎是:
使用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模式以获得较大的值,这可能是这里的情况,尽管惩罚应该更高.