Mik*_*ike 4 python optimization numpy scientific-computing cython
我正在寻找一种方法,使用Python/Cython/Numpy快速将许多4x4矩阵相乘,任何人都可以提出任何建议吗?
为了显示我当前的尝试,我有一个需要计算的算法
A_1 * A_2 * A_3 * ... * A_N
Run Code Online (Sandbox Code Playgroud)
每一个
A_i != A_j
Run Code Online (Sandbox Code Playgroud)
Python中的一个例子:
means = array([0.0, 0.0, 34.28, 0.0, 0.0, 3.4])
stds = array([ 4.839339, 4.839339, 4.092728, 0.141421, 0.141421, 0.141421])
def fn():
steps = means+stds*numpy.random.normal(size=(60,6))
A = identity(4)
for step in steps:
A = dot(A, transform_step_to_4by4(step))
%timeit fn()
1000 loops, best of 3: 570 us per loop
Run Code Online (Sandbox Code Playgroud)
在Cython/Numpy中实现此算法比使用具有所有优化的Eigen/C++的等效代码慢大约100倍.不过,我真的不想使用C++.
如果你不得不进行Python函数调用来生成你想要乘法的每个矩阵,那么你基本上是在性能方面搞砸了.但是如果你可以对transform_step_to_4by4
函数进行矢量化,并让它返回一个有形状的数组,(n, 4, 4)
那么你可以节省一些时间matrix_multiply
:
import numpy as np
from numpy.core.umath_tests import matrix_multiply
matrices = np.random.rand(64, 4, 4) - 0.5
def mat_loop_reduce(m):
ret = m[0]
for x in m[1:]:
ret = np.dot(ret, x)
return ret
def mat_reduce(m):
while len(m) % 2 == 0:
m = matrix_multiply(m[::2], m[1::2])
return mat_loop_reduce(m)
In [2]: %timeit mat_reduce(matrices)
1000 loops, best of 3: 287 us per loop
In [3]: %timeit mat_loop_reduce(matrices)
1000 loops, best of 3: 721 us per loop
In [4]: np.allclose(mat_loop_reduce(matrices), mat_reduce(matrices))
Out[4]: True
Run Code Online (Sandbox Code Playgroud)
你现在有log(n)Python调用而不是n,有利于2.5倍的加速,对于n = 1024,它将接近10倍.显然matrix_multiply
是一个ufunc,因此有一个.reduce
方法,它将允许你的代码在Python中不运行循环.我无法让它运行,不断收到一个神秘的错误:
In [7]: matrix_multiply.reduce(matrices)
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
RuntimeError: Reduction not defined on ufunc with signature
Run Code Online (Sandbox Code Playgroud)