Pet*_*ann 4 python performance numpy
我必须迭代二维整数数组中的所有项并更改值(根据某些规则,不重要).
我很惊讶python运行时和C#或java运行时之间的性能差异如何.我写了完全错误的python代码(v2.7.2)吗?
import numpy
a = numpy.ndarray((5000,5000), dtype = numpy.int32)
for x in numpy.nditer(a.T):
x = 123
Run Code Online (Sandbox Code Playgroud)
>python -m timeit -n 2 -r 2 -s "import numpy; a = numpy.ndarray((5000,5000), dtype=numpy.int32)" "for x in numpy.nditer(a.T):" " x = 123"
2 loops, best of 2: 4.34 sec per loop
Run Code Online (Sandbox Code Playgroud)
例如,C#代码只执行50ms,即python几乎慢100倍!(假设matrix变量已经初始化)
for (y = 0; y < 5000; y++)
for (x = 0; x < 5000; x++)
matrix[y][x] = 123;
Run Code Online (Sandbox Code Playgroud)
Joe*_*ton 13
是的!在python中迭代numpy数组很慢.(比迭代python列表慢.)
通常,您可以避免直接迭代它们.
如果你能给我们一个你正在改变事物的规则的例子,很有可能它很容易被矢量化.
作为玩具示例:
import numpy as np
x = np.linspace(0, 8*np.pi, 100)
y = np.cos(x)
x[y > 0] = 100
Run Code Online (Sandbox Code Playgroud)
但是,在许多情况下,您必须迭代,或者由于算法(例如,有限差分方法)或者减少临时数组的内存成本.
Sve*_*ach 10
你给出的例子可能是为了将二维NumPy数组的所有项都设置为123.这可以像这样有效地完成:
a.fill(123)
Run Code Online (Sandbox Code Playgroud)
要么
a[:] = 123
Run Code Online (Sandbox Code Playgroud)
Python是比C或C#更动态的语言。循环如此缓慢的主要原因是,每次循环,CPython解释器都会做一些额外的工作,从而浪费时间:具体地说,它是将名称x与迭代器中的下一个对象绑定在一起,然后在评估赋值时x再次查找名称。
正如@Sven Marnach指出的那样,您可以调用一个方法函数,numpy.fill()并且它很快。该函数是用C或Fortran编译的,它将仅循环遍历numpy.array数据结构的地址并填充值。动态性比Python小得多,这对于这种简单的情况很有用。
但是现在考虑PyPy。在PyPy下运行程序后,JIT将分析您的代码实际在做什么。在此示例中,它指出该名称x仅用于分配,并且可以优化绑定名称的过程。这个例子应该是PyPy极大地加速的例子。PyPy的速度可能会比普通Python快十倍(因此,速度仅为C的十分之一,而不是C的1/100)。
据我了解,PyPy暂时不会与Numpy一起使用,因此您不能仅在PyPy下运行现有的Numpy代码。但是,这一天就要到了。
我为PyPy感到兴奋。它提供了希望,我们可以使用一种非常高级的语言(Python)进行编写,而又获得了几乎可以用“便携式汇编语言”(C)进行编写的性能。对于像这样的示例,通过使用来自CPU(SSE2,NEON或其他)的SIMD指令,Numpy甚至可以击败朴素的C代码的性能。对于此示例,使用SIMD,您可以在每个循环中将四个整数设置为123,这将比普通C循环更快。(除非C编译器也使用SIMD优化!考虑到这种情况,很可能会发生这种情况。因此,对于本示例,我们回到“接近C的速度”,而不是更快。但是,我们可以想象到棘手的情况C编译器不够聪明,无法进行优化(未来的PyPy可能会优化)。)
但是暂时不要介意PyPy。如果要使用Numpy,最好学习所有类似的功能numpy.fill(),以加快代码的速度。