Python numpy.einsum(';ij,ji';a,b)性能问题

Python numpy.einsum(';ij,ji';a,b)性能问题,python,numpy,numpy-einsum,Python,Numpy,Numpy Einsum,有人能解释一下,为什么numpy.einsum('ij,ji',A,B)比numpy.einsum('ij,ij',A,B)慢得多,如下所示 In [1]: import numpy as np In [2]: a = np.random.rand(1000,1000)

有人能解释一下,为什么numpy.einsum('ij,ji',A,B)比numpy.einsum('ij,ij',A,B)慢得多,如下所示

In [1]: import numpy as np
In [2]: a = np.random.rand(1000,1000)                                                                                                                                
In [3]: b = np.random.rand(1000,1000)                                                                                                                                
In [4]: timeit np.einsum('ij,ij', a, b)                                                                                                                               
532 µs ± 5.36 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [5]: timeit np.einsum('ij,ji', a, b)                                                                                                                               
1.28 ms ± 20.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
问候,, 马雷克第一嫌疑犯:

在第一种情况下,
a
b
的内存都是以连续的顺序模式访问的

在第二种情况下,
b
的内存在内部循环中以1000个元素(8000字节)的速度访问

大多数现代x86处理器都有32KiB的一级缓存和64字节的缓存线,这意味着总共有512条缓存线。因此,在外循环迭代之间,整个一级缓存被逐出~两次

请注意,如果您运行

timeit np.einsum('ij,ji', a, b.T)
您应该得到与第一个示例大致相同的时间

同样地

timeit np.einsum('ij,ij', a, b.T)
应给出与第二个示例相同的时间。

第一个嫌疑犯:

在第一种情况下,
a
b
的内存都是以连续的顺序模式访问的

在第二种情况下,
b
的内存在内部循环中以1000个元素(8000字节)的速度访问

大多数现代x86处理器都有32KiB的一级缓存和64字节的缓存线,这意味着总共有512条缓存线。因此,在外循环迭代之间,整个一级缓存被逐出~两次

请注意,如果您运行

timeit np.einsum('ij,ji', a, b.T)
您应该得到与第一个示例大致相同的时间

同样地

timeit np.einsum('ij,ij', a, b.T)

应给出与第二个示例相同的时间。

还应将“b”数组作为b1=np进行预处理。asfortanarray(b)影响计时:np.einsum('ij,ji',a,b1)比np.einsum('ij,ij',a,b1)快。我认为这证实了答案。谢谢另外,将“b”数组作为b1=np进行预处理。asfortanarray(b)会影响计时:np.einsum('ij,ji',a,b1)比np.einsum('ij,ij',a,b1)快。我认为这证实了答案。谢谢