#python #numpy #matrix #jupyter-notebook
Вопрос:
У меня есть коллекция массивов K0,K1,K2....Kn
, определенных в 1D массиве z
Мне нужна следующая симметричная матрица самым быстрым возможным способом без использования цикла for.
[np.trapz(K0*K0,z) np.trapz(K0*K1,z) np.trapz(K0*K2,z) np.trapz(K0*K3,z)...]
[ . np.trapz(K1*K1,z) np.trapz(K1*K2,z) np.trapz(K1*K3,z)...]
A = [ . . np.trapz(K2*K2,z) np.trapz(K2*K3,z)...]
[ . . . np.trapz(K3*K3,z)...]
[ . . . . ]
Ниже приведен самый быстрый, с которым я мог справиться (все еще недостаточно быстрый для больших n… n>10000
).
Я храню этот набор K
s в объединенном массиве под названием KK
KK = []
for i in range(n):
KK.append(Ki)
KK = np.array(KK)
A = np.zeros((n,n))
for i in range(n):
A[i,i:] = A[i:,i] = np.trapz((KK[i]*KK[i:]),z)
Каков более быстрый способ сделать это? Меня не волнует, насколько неэлегантным или непитоническим является решение. Я просто хочу увеличить скорость.
Комментарии:
1. Похоже, вы смешиваете здесь математику и нотацию Python. Лучше использовать только нотацию Python. Как именно создается «KK»?
2. Внесла изменения. Я понимаю, что K0(z) и т. Д. Заставляет вас думать, что K0-это функция. Но я не могу точно представить эти величины без латекса
Ответ №1:
Вы используете свойства симметричной матрицы, что делает ее очень эффективной. Один из способов ускорить процесс-использовать Numba
import numpy as np
import numba as nb
@nb.njit(cache=True, nogil=True, parallel=True)
def fun(KK,z,n):
A = np.zeros((n,n))
for i in nb.prange(n):
A[i,i:] = A[i:,i] = np.trapz((KK[i]*KK[i:]),z)
return A
Старые ответы
np.trapz(KK.T[:,:,None]@KK.T[:,None,:],z,axis=0) # using matrix multiplication
np.trapz(np.einsum('ik,jk->ijk',KK,KK),z,axis=2) # Using einsum
Комментарии:
1. Спасибо вам за ответы. Однако это занимает гораздо больше времени, чем моя попытка цикла for.
2. @ПрасадМани, насколько велики ваши числа n и числа z ? Это зависит от того, насколько хорошо управляется память. если n x n x len(z) байтов не помещается в вашей памяти, они будут очень медленными. В этом случае зацикливание — лучший способ.
3. Я отредактировал его с помощью Numba, это будет быстрее.
4. Это было фантастически! Большое вам спасибо. Он вычисляет не более чем в два раза быстрее (и в лучшем случае в 5 раз быстрее), а также использует мощность процессора от бездействующих процессоров в узле. Цикл «для» этого не делал, что делало все это медленным
5. @ПрасадМани я добавил их