是什么让C比Python更快?

时间:2023-01-15 10:36:26

I know this is probably a very obvious answer and that I'm exposing myself to less-than-helpful snarky comments, but I don't know the answer so here goes.

我知道这可能是一个非常明显的答案,而且我将自己暴露给不那么有用的讽刺评论,但我不知道答案所以这里就是这样。

If Python compiles to bytecode at runtime, is it just that initial compiling step that takes longer? If that's the case wouldn't that just be a small upfront cost in the code (ie if the code is running over a long period of time, do the differences between C and python diminish?)

如果Python在运行时编译为字节码,那么只需要花费更长时间的初始编译步骤吗?如果是这样的话,那么代码中的前期成本就不会那么小(即如果代码运行的时间很长,那么C和python之间的差异是否会减少?)

2 个解决方案

#1


13  

It's not merely the fact that Python code is interpreted which makes it slower, although that definitely sets a limit to how fast you can get.

这不仅仅是因为Python代码被解释使得速度变慢,尽管这肯定会限制你获得的速度。

If the bytecode-centric perspective were right, then to make Python code as fast as C all you'd have to do is replace the interpreter loop with direct calls to the functions, eliminating any bytecode, and compile the resulting code. But it doesn't work like that. You don't have to take my word for it, either: you can test it for yourself. Cython converts Python code to C, but a typical Python function converted and then compiled doesn't show C-level speed. All you have to do is look at some typical C code thus produced to see why.

如果以字节码为中心的观点是正确的,那么为了使Python代码与C一样快,你所要做的就是用直接调用函数替换解释器循环,消除任何字节码,并编译生成的代码。但它并不像那样。你也不必接受我的话:你可以自己测试一下。 Cython将Python代码转换为C,但转换然后编译的典型Python函数不显示C级速度。您所要做的就是查看一些典型的C代码,以便了解原因。

The real challenge is multiple dispatch (or whatever the right jargon is -- I can't keep it all straight), by which I mean the fact that whereas a+b if a and b are both known to be integers or floats can compile down to one op in C, in Python you have to do a lot more to compute a+b (get the objects that the names are bound to, go via __add__, etc.)

真正的挑战是多次派遣(或者任何正确的行话 - 我不能保持一切直线),我的意思是这样的事实,而a + b如果a和b都知道是整数或浮点数可以编译在C中一个操作,在Python中你必须做更多的事情来计算一个+ b(获取名称绑定的对象,通过__add__等)

This is why to make Cython reach C speeds you have to specify the types in the critical path; this is how Shedskin makes Python code fast using (Cartesian product) type inference to get C++ out of it; and how PyPy can be fast -- the JIT can pay attention to how the code is behaving and specialize on things like types. Each approach eliminates dynamism, whether at compile time or at runtime, so that it can generate code which knows what it's doing.

这就是为什么要使Cython达到C速度,你必须指定关键路径中的类型;这就是Shedskin如何使用(笛卡尔积)类型推断快速制作Python代码以使C ++脱离它;以及PyPy如何快速--JIT可以关注代码的行为方式,并专注于类型之类的事情。无论是在编译时还是在运行时,每种方法都消除了动态,因此它可以生成知道它正在做什么的代码。

#2


6  

Byte codes are not natural to the CPU so they need interpretation (by a CPU native code called interpreter). The advantage of byte code is that it enables optimizations, pre-computations, and saves space. C compiler produces machine code and machine code does not need interpretation, it is native to CPU.

字节代码对于CPU来说并不自然,因此它们需要解释(通过称为解释器的CPU本机代码)。字节代码的优点是它可以实现优化,预计算和节省空间。 C编译器生成机器代码,机器代码不需要解释,它是CPU原生的。

#1


13  

It's not merely the fact that Python code is interpreted which makes it slower, although that definitely sets a limit to how fast you can get.

这不仅仅是因为Python代码被解释使得速度变慢,尽管这肯定会限制你获得的速度。

If the bytecode-centric perspective were right, then to make Python code as fast as C all you'd have to do is replace the interpreter loop with direct calls to the functions, eliminating any bytecode, and compile the resulting code. But it doesn't work like that. You don't have to take my word for it, either: you can test it for yourself. Cython converts Python code to C, but a typical Python function converted and then compiled doesn't show C-level speed. All you have to do is look at some typical C code thus produced to see why.

如果以字节码为中心的观点是正确的,那么为了使Python代码与C一样快,你所要做的就是用直接调用函数替换解释器循环,消除任何字节码,并编译生成的代码。但它并不像那样。你也不必接受我的话:你可以自己测试一下。 Cython将Python代码转换为C,但转换然后编译的典型Python函数不显示C级速度。您所要做的就是查看一些典型的C代码,以便了解原因。

The real challenge is multiple dispatch (or whatever the right jargon is -- I can't keep it all straight), by which I mean the fact that whereas a+b if a and b are both known to be integers or floats can compile down to one op in C, in Python you have to do a lot more to compute a+b (get the objects that the names are bound to, go via __add__, etc.)

真正的挑战是多次派遣(或者任何正确的行话 - 我不能保持一切直线),我的意思是这样的事实,而a + b如果a和b都知道是整数或浮点数可以编译在C中一个操作,在Python中你必须做更多的事情来计算一个+ b(获取名称绑定的对象,通过__add__等)

This is why to make Cython reach C speeds you have to specify the types in the critical path; this is how Shedskin makes Python code fast using (Cartesian product) type inference to get C++ out of it; and how PyPy can be fast -- the JIT can pay attention to how the code is behaving and specialize on things like types. Each approach eliminates dynamism, whether at compile time or at runtime, so that it can generate code which knows what it's doing.

这就是为什么要使Cython达到C速度,你必须指定关键路径中的类型;这就是Shedskin如何使用(笛卡尔积)类型推断快速制作Python代码以使C ++脱离它;以及PyPy如何快速--JIT可以关注代码的行为方式,并专注于类型之类的事情。无论是在编译时还是在运行时,每种方法都消除了动态,因此它可以生成知道它正在做什么的代码。

#2


6  

Byte codes are not natural to the CPU so they need interpretation (by a CPU native code called interpreter). The advantage of byte code is that it enables optimizations, pre-computations, and saves space. C compiler produces machine code and machine code does not need interpretation, it is native to CPU.

字节代码对于CPU来说并不自然,因此它们需要解释(通过称为解释器的CPU本机代码)。字节代码的优点是它可以实现优化,预计算和节省空间。 C编译器生成机器代码,机器代码不需要解释,它是CPU原生的。