在 Python 中更快地定义 "matrix multiplication"
Faster definition of "matrix multiplication" in Python
我需要从头开始定义矩阵乘法,而不是将每个常数相乘,每个常数实际上是另一个数组,任何两个数组都需要“卷积”在一起(我认为没有必要定义什么卷积在这里)。
我制作了一张图片,希望能更好地解释我想说的内容:
我必须使用的代码是这样的:
for row in range(arr1.shape[2]):
for column in range(arr2.shape[3]):
for index in range(arr2.shape[2]): # Could also be "arr1.shape[3]"
out[:, :, row, column] += convolve(
arr2[:, :, : , column][:, :, index],
arr1[:, :, row, : ][:, :, index]
)
然而,这种方法对我来说非常慢,所以我想知道是否有更快的方法来做到这一点。
如果中间体适合内存,则以下应该相当有效
import numpy as np
from scipy.signal import fftconvolve,convolve
# example
rng = np.random.default_rng()
A = rng.random((5,6,2,3))
B = rng.random((4,3,3,4))
# custom matmul
Ae,Be = A[...,None],B[:,:,None]
shsh = np.maximum(Ae.shape[2:],Be.shape[2:])
Ae = np.broadcast_to(Ae,(*Ae.shape[:2],*shsh))
Be = np.broadcast_to(Be,(*Be.shape[:2],*shsh))
C = fftconvolve(Ae,Be,axes=(0,1),mode='valid').sum(3)
# original loop for reference
out = np.zeros_like(C)
for row in range(A.shape[2]):
for column in range(B.shape[3]):
for index in range(B.shape[2]): # Could also be "A.shape[3]"
out[:, :, row, column] += convolve(
B[:, :, : , column][:, :, index],
A[:, :, row, : ][:, :, index],
mode='valid'
)
print(np.allclose(C,out))
# True
通过批量进行卷积,我们减少了必须执行的 fft 的总数。
如果需要,可以通过使用 einsum
对傅立叶 space 进行求和来进一步优化速度和内存。不过,这需要手动进行 fft 卷积。
我需要从头开始定义矩阵乘法,而不是将每个常数相乘,每个常数实际上是另一个数组,任何两个数组都需要“卷积”在一起(我认为没有必要定义什么卷积在这里)。
我制作了一张图片,希望能更好地解释我想说的内容:
我必须使用的代码是这样的:
for row in range(arr1.shape[2]):
for column in range(arr2.shape[3]):
for index in range(arr2.shape[2]): # Could also be "arr1.shape[3]"
out[:, :, row, column] += convolve(
arr2[:, :, : , column][:, :, index],
arr1[:, :, row, : ][:, :, index]
)
然而,这种方法对我来说非常慢,所以我想知道是否有更快的方法来做到这一点。
如果中间体适合内存,则以下应该相当有效
import numpy as np
from scipy.signal import fftconvolve,convolve
# example
rng = np.random.default_rng()
A = rng.random((5,6,2,3))
B = rng.random((4,3,3,4))
# custom matmul
Ae,Be = A[...,None],B[:,:,None]
shsh = np.maximum(Ae.shape[2:],Be.shape[2:])
Ae = np.broadcast_to(Ae,(*Ae.shape[:2],*shsh))
Be = np.broadcast_to(Be,(*Be.shape[:2],*shsh))
C = fftconvolve(Ae,Be,axes=(0,1),mode='valid').sum(3)
# original loop for reference
out = np.zeros_like(C)
for row in range(A.shape[2]):
for column in range(B.shape[3]):
for index in range(B.shape[2]): # Could also be "A.shape[3]"
out[:, :, row, column] += convolve(
B[:, :, : , column][:, :, index],
A[:, :, row, : ][:, :, index],
mode='valid'
)
print(np.allclose(C,out))
# True
通过批量进行卷积,我们减少了必须执行的 fft 的总数。
如果需要,可以通过使用 einsum
对傅立叶 space 进行求和来进一步优化速度和内存。不过,这需要手动进行 fft 卷积。