Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 相似代码之间的numpy速度差异巨大_Python_Performance_Numpy - Fatal编程技术网

Python 相似代码之间的numpy速度差异巨大

Python 相似代码之间的numpy速度差异巨大,python,performance,numpy,Python,Performance,Numpy,为什么以下L2标准计算之间存在如此大的速度差异: a = np.arange(1200.0).reshape((-1,3)) %timeit [np.sqrt((a*a).sum(axis=1))] 100000 loops, best of 3: 12 µs per loop %timeit [np.sqrt(np.dot(x,x)) for x in a] 1000 loops, best of 3: 814 µs per loop %timeit [np.linalg.norm(x)

为什么以下L2标准计算之间存在如此大的速度差异:

a = np.arange(1200.0).reshape((-1,3))

%timeit [np.sqrt((a*a).sum(axis=1))]
100000 loops, best of 3: 12 µs per loop

%timeit [np.sqrt(np.dot(x,x)) for x in a]
1000 loops, best of 3: 814 µs per loop

%timeit [np.linalg.norm(x) for x in a]
100 loops, best of 3: 2 ms per loop
就我所见,这三种方法都产生了相同的结果

以下是numpy.linalg.norm函数的源代码:

x = asarray(x)

# Check the default case first and handle it immediately.
if ord is None and axis is None:
    x = x.ravel(order='K')
    if isComplexType(x.dtype.type):
        sqnorm = dot(x.real, x.real) + dot(x.imag, x.imag)
    else:
        sqnorm = dot(x, x)
    return sqrt(sqnorm)

编辑:有人建议一个版本可以并行化,但我检查了一下,事实并非如此。这三个版本都消耗12.5%的CPU(与我的4物理/8虚拟核心Xeon CPU上的Python代码通常一样。

np.dot通常会调用BLAS库函数-因此,它的速度将取决于您的numpy版本链接到哪个BLAS库。一般来说,我希望它具有更大的恒定开销,但扩展性会更好大小增加。但是,您从列表理解中调用它(实际上是一个普通的Python
for
循环)这一事实可能会否定使用BLAS的任何性能优势

如果您放弃列表理解并使用
axis=
kwarg,
np.linalg.norm
与您的第一个示例相当,但是
np.einsum
比两者都快得多:

In [1]: %timeit np.sqrt((a*a).sum(axis=1))
The slowest run took 10.12 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 11.1 µs per loop

In [2]: %timeit np.linalg.norm(a, axis=1)
The slowest run took 14.63 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 13.5 µs per loop

# this is what np.linalg.norm does internally
In [3]: %timeit np.sqrt(np.add.reduce(a * a, axis=1))
The slowest run took 34.05 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 10.7 µs per loop

In [4]: %timeit np.sqrt(np.einsum('ij,ij->i',a,a))
The slowest run took 5.55 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 5.42 µs per loop

更多时间:
[math.sqrt(np.dot(x,x))表示A中的x]
np.sqrt(np.einsum('ij,ij->i',A,A))
主要区别在于在解释的Python代码和编译的C代码中执行的操作。我注意到的一点是,第一个方法给出的结果的精度比其他方法小得多。例如,第一个方法生成的最终数字是2074.9973494,而最后两个方法生成的最终数字是2074.9973493958973.TrisNefzger,我用dtype检查了结果,在所有三种情况下都是float64。列表和数组有不同的规则来显示浮点数的有效数字。因此,显示并没有告诉你多少浮点数类型。我很好奇,当我们用axis=1参数替换Python列表理解时,会有什么变化?或者,为什么Python是“for loop”比C“for loop”慢。要回答您的第一个问题,当您使用矢量化时(即
axis=1
而不是列表comp)numpy本质上是在C代码级别而不是在Python中对数组元素进行循环。至于为什么C中的循环比Python快……这是一个相当大的问题。简单的答案是,运行时性能较慢是您为换取Python出色的高级语言功能(如类型检查、自动垃圾处理、C)而付出的代价收集等(有关更多详细信息,请参阅)你说的矢量化是指Intel AVX吗?关于Python vs C,我不太清楚:Python字节码是否仍在执行所有检查/垃圾收集等操作,还是在编译字节码时只执行一次?如果字节码没有这种开销,是什么使它比本机代码慢?在numpy领域,我们倾向于使用se“矢量化"泛指。Python编译器生成的字节码与C等编译的本机指令不同,而是一组虚拟机指令,在运行时执行类型检查、垃圾收集等。除了标准的CPython之外,还有其他Python实现清空各种运行时优化(例如,您可能听说过PyPy,它使用优化JIT编译器)。这远远超出了我在SE问题的评论中可以合理回答的范围。您可以找到关于CPython内部和