Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.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 为什么用Numba进行矩阵乘法很慢?_Python_Numpy_Numba - Fatal编程技术网

Python 为什么用Numba进行矩阵乘法很慢?

Python 为什么用Numba进行矩阵乘法很慢?,python,numpy,numba,Python,Numpy,Numba,我试图找到一个解释,为什么我用Numba进行矩阵乘法要比用NumPy的点函数慢得多。虽然我使用最基本的代码来编写带有Numba的矩阵乘法函数,但我不认为性能显著降低是由于该算法造成的。为了简单起见,我考虑两个k×k方阵,A和B。 1 @njit('f8[:,:](f8[:,:], f8[:,:])') 2 def numba_dot(A, B): 3 4 k=A.shape[1] 5 C = np.zeros((k, k)) 6 7

我试图找到一个解释,为什么我用Numba进行矩阵乘法要比用NumPy的点函数慢得多。虽然我使用最基本的代码来编写带有Numba的矩阵乘法函数,但我不认为性能显著降低是由于该算法造成的。为了简单起见,我考虑两个k×k方阵,A和B。
1     @njit('f8[:,:](f8[:,:], f8[:,:])')
2     def numba_dot(A, B):
3
4         k=A.shape[1]
5         C = np.zeros((k, k))
6
7         for i in range(k):
8             for j in range(k):
9
10                 tmp = 0.
11                for l in range(k):
12                    tmp += A[i, l] * B[l, j]
13     
14                C[i, j] = tmp
15
16         return C
使用两个随机矩阵1000 x 1000重复运行此代码,通常至少需要1.5秒才能完成。 另一方面,如果我不更新矩阵C,即如果我删除第14行,或为了测试而替换它,例如,使用以下行:

14                C[i, j] = i * j
代码大约在1-5毫秒内完成。相比之下,NumPy的点函数需要大约10毫秒的矩阵乘法


上面的矩阵乘法代码和这个小变化之间的运行时间差异的原因是什么?有没有一种方法可以将变量tmp的值存储在C[i,j]中而不会显著降低代码的性能?

本机
NumPy
实现使用矢量化操作。如果您的CPU支持这些,处理速度会快得多。当前的微处理器有片内矩阵乘法,它将数据传输和向量运算流水线化

您的实现执行k^3循环迭代;10亿件事情都需要一些不平凡的时间。
您的代码指定要单独执行每个单元的操作,10亿个不同的操作,而不是并行和流水线执行大约5k个操作。

您的算法绝对没有优化。一个关于如何实现矩阵乘法的真实示例看起来像Numpy在本例中调用BLAS函数dgemm。如果输入是连续的,Numba也会这样做。例如,
@njit('f8[:,::1](f8[:,::1],f8[:,::1]))
谢谢你的回复。出于某种原因,对于连续输入,我也会得到类似的运行时间。只需在Numba中调用np.dot(使用连续数组)。在这两种情况下,numpy和numba都会做同样的事情(调用外部BLAS库)。这个链接只是为了展示现实世界中矩阵乘法是多么复杂。这是一个很好的学习方法,但是如果你不想计算点积,这就是方法。您也可以在C语言中尝试(如果不对算法进行一些改进,速度仍然会慢100倍以上)。还要考虑编译器试图优化无用部分。如果您编写C[i,j]=i*j,整个内部循环将被检测为无用。谢谢您的回答。我认为我的例子表明,必须执行的不仅仅是操作的数量,还有操作的类型。当按照描述修改代码并使用Numba编译代码时,三个循环可以在与NumPy的点函数类似的时间内执行。