与fortran或C相比,numpy.einsum是否有效?

时间:2016-02-19 08:46:30

标签: python performance numpy blas numpy-einsum

我写了一个非常耗时的numpy程序。在对其进行分析之后,我发现大部分时间都花费在numpy.einsum上。

虽然numpy是LAPACK或BLAS的包装器,但我不知道numpy.einsum的性能是否与LAPACK或BLAS中的对应物相当。

那么,如果我切换到fortran或C,我会获得更多性能提升吗?

1 个答案:

答案 0 :(得分:3)

Numpy仅对BLAS指定的基本操作包装BLAS。其中包括dotinnerproductvdotmatmul(1.10中的新内容)以及依赖它的函数(tensordot等)。另一方面,einsum只调用BLAS进行允许回退的操作(从Numpy 1.14.0开始)。

如果你的问题可以分解成几个BLAS操作,那么我建议你先在Numpy中尝试一下。它可能需要一些临时数组(即使您编写使用BLAS的C / FORTRAN,情况仍然如此)。您可以使用函数的out=参数来消除某些数组创建开销。

但大部分时间,你使用的是einsum,因为它在BLAS中无法表达。看一个简单的例子:

a = np.arange(60.).reshape(3,4,5)
b = np.arange(24.).reshape(4,3,2)
c = np.einsum('ijk,jil->kl', a, b)

要在基本操作中表达上述内容,您需要交换b中的前两个轴,对前两个维度进行逐元素乘法,然后对每个索引{{1}进行求和。 }和k

l

你不能BLAS那样。更新:上述问题可以表示为矩阵乘法,可以使用BLAS加速。请参阅@ali_m的评论。对于足够大的阵列,BLAS方法更快。

同时,请注意c2 = np.ndarray((5, 2)) b2 = np.swapaxes(b, 0, 1) def manualeinsum(c2, a, b): ny, nx = c2.shape for k in range(ny): for l in range(nx): c2[k, l] = np.sum(a[..., k]*b2[...,l]) manualeinsum(c2, a, b2) 本身是用C语言编写的,为给定的索引创建特定于维度的迭代器,并且还针对SSE进行了优化。