相似代码之间在numpy中存在巨大的速度差异

Mic*_*lSB 5 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) for x in a]
100 loops, best of 3: 2 ms per loop
Run Code Online (Sandbox Code Playgroud)

据我所知,这三个结果均相同。

这是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)
Run Code Online (Sandbox Code Playgroud)

编辑:有人建议可以并行化一个版本,但我检查了,情况并非如此。所有这三个版本都消耗12.5%的CPU(通常在我的4物理/ 8虚拟内核Xeon CPU上使用Python代码)。

ali*_*i_m 5

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

\n\n

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

\n\n
In [1]: %timeit np.sqrt((a*a).sum(axis=1))\nThe slowest run took 10.12 times longer than the fastest. This could mean that an intermediate result is being cached \n100000 loops, best of 3: 11.1 \xc2\xb5s per loop\n\nIn [2]: %timeit np.linalg.norm(a, axis=1)\nThe slowest run took 14.63 times longer than the fastest. This could mean that an intermediate result is being cached \n100000 loops, best of 3: 13.5 \xc2\xb5s per loop\n\n# this is what np.linalg.norm does internally\nIn [3]: %timeit np.sqrt(np.add.reduce(a * a, axis=1))\nThe slowest run took 34.05 times longer than the fastest. This could mean that an intermediate result is being cached \n100000 loops, best of 3: 10.7 \xc2\xb5s per loop\n\nIn [4]: %timeit np.sqrt(np.einsum('ij,ij->i',a,a))\nThe slowest run took 5.55 times longer than the fastest. This could mean that an intermediate result is being cached \n100000 loops, best of 3: 5.42 \xc2\xb5s per loop\n
Run Code Online (Sandbox Code Playgroud)\n