Вызовы Numpy-Blas не всегда являются самой быстрой возможностью
В задачах, где вам нужно вычислить множество обратных значений, собственных значений, скалярных произведений небольших матриц 3x3 или подобных случаев, numpy-MKL, который я использую, часто может быть значительно лучше.
Эти внешние подпрограммы Blas обычно создаются для задач с большими матрицами, для меньших вы можете написать стандартный алгоритм или посмотреть, например. Интел ИПП.
Также имейте в виду, что Numpy по умолчанию использует массивы C-упорядочения (последнее измерение изменяется быстрее всего). Для этого примера я взял код из Matrix inversion (3,3) python - жестко запрограммирован против numpy.linalg.inv и немного модифицировал его.
import numpy as np
import numba as nb
import time
@nb.njit(fastmath=True)
def inversion(m):
minv=np.empty(m.shape,dtype=m.dtype)
for i in range(m.shape[0]):
determinant_inv = 1./(m[i,0]*m[i,4]*m[i,8] + m[i,3]*m[i,7]*m[i,2] + m[i,6]*m[i,1]*m[i,5] - m[i,0]*m[i,5]*m[i,7] - m[i,2]*m[i,4]*m[i,6] - m[i,1]*m[i,3]*m[i,8])
minv[i,0]=(m[i,4]*m[i,8]-m[i,5]*m[i,7])*determinant_inv
minv[i,1]=(m[i,2]*m[i,7]-m[i,1]*m[i,8])*determinant_inv
minv[i,2]=(m[i,1]*m[i,5]-m[i,2]*m[i,4])*determinant_inv
minv[i,3]=(m[i,5]*m[i,6]-m[i,3]*m[i,8])*determinant_inv
minv[i,4]=(m[i,0]*m[i,8]-m[i,2]*m[i,6])*determinant_inv
minv[i,5]=(m[i,2]*m[i,3]-m[i,0]*m[i,5])*determinant_inv
minv[i,6]=(m[i,3]*m[i,7]-m[i,4]*m[i,6])*determinant_inv
minv[i,7]=(m[i,1]*m[i,6]-m[i,0]*m[i,7])*determinant_inv
minv[i,8]=(m[i,0]*m[i,4]-m[i,1]*m[i,3])*determinant_inv
return minv
#I was to lazy to modify the code from the link above more thoroughly
def inversion_3x3(m):
m_TMP=m.reshape(m.shape[0],9)
minv=inversion(m_TMP)
return minv.reshape(minv.shape[0],3,3)
#Testing
A = np.random.rand(1000000,3,3)
#Warmup to not measure compilation overhead on the first call
#You may also use @nb.njit(fastmath=True,cache=True) but this has also about 0.2s
#overhead on fist call
Ainv = inversion_3x3(A)
t1=time.time()
Ainv = inversion_3x3(A)
print(time.time()-t1)
t1=time.time()
Ainv2 = np.linalg.inv(A)
print(time.time()-t1)
print(np.allclose(Ainv2,Ainv))
Производительность
np.linalg.inv: 0.36 s
inversion_3x3: 0.031 s
person
max9111
schedule
02.04.2018
for
такие медленные в Python? - person Robert Harvey   schedule 15.08.2012inv
занимает у меня около 51,8 мкс.for i in range(100): pass
занимает 2,89 мкс, поэтому накладные расходы на цикл для каждого inv совершенно незначительны. Время вычисления среза составляет около 1,2 мкс. Я не думаю, чтоfor
скорость цикла играет здесь роль, и толькоtimeit
данные убедят меня в обратном. - person DSM   schedule 15.08.2012timeit
является вашим другом, и вам следует действительно беспокоиться об оптимизации вашего самого внутреннего цикла только тогда, когда у вас есть вложенные циклы и т. д. и т. д.). - person mgilson   schedule 15.08.2012