Mam dwie macierze NxN, które chcę, aby pomnożyć razem: A i B. W NumPy użyłem:NumPy Matrix Mnożenie Wydajność dla macierzy o znanej strukturze
import numpy as np
C = np.dot(A, B)
Jednak zdarza mi się, że dla macierzy B tylko rząd n i kolumna n są niezerowe (wynika to bezpośrednio z formuły analitycznej, która wytworzyła matrycę i jest bez wątpienia zawsze taka sytuacja).
nadziei na wykorzystanie tego faktu i zmniejszenia liczby powieleń wymaganych do wytworzenia c, I otrzymuje powyżej:
import numpy as np
for row in range(0, N):
for col in range(0, N):
if col != n:
C[row, col] = A[row, n]*B[n, col] #Just one scalar multiplication
else:
C[row, col] = np.dot(A[row], B[:, n])
analitycznie, należy zmniejszyć całkowitą złożoność w następujący sposób: W przypadku ogólnym (bez użycia fantazyjnych sztuczek, tylko podstawowe mnożenie macierzy) C = AB, gdzie A i B są oba NxN, powinno być O (N^3). Oznacza to, że wszystkie N wierszy musi pomnożyć wszystkich kolumn N, a każdy z tych produktów kropek zawiera N mnożenia => O (N N N) = O (N^3). #
Wykorzystanie struktury B jako Zrobiłem powyżej jednak powinien pójść jako O (N^2 + N^2) = O (2N^2) = O (N^2). Oznacza to, że wszystkie wiersze N muszą pomnożyć wszystkie kolumny N, jednak dla wszystkich z nich (z wyjątkiem tych obejmujących "B [:, n]") wymagane jest tylko jedno zwielokrotnienie skalarne: tylko jeden element "B [:, m]" jest niezerowe dla m! = n. Gdy n == m, które wystąpią N razy (jeden raz dla każdego wiersza A, który musi pomnożyć kolumnę n z B), musi wystąpić N multiplikacji skalarnych. #
Jednak pierwszy blok kodu (za pomocą np.dot (A, B)) jest znacznie szybszy. Jestem świadomy (poprzez informacje takie jak: Why is matrix multiplication faster with numpy than with ctypes in Python?), że szczegóły implementacji niskiego poziomu np.dot są prawdopodobnie za to odpowiedzialne. Moje pytanie brzmi następująco: Jak mogę wykorzystać strukturę macierzy B, aby poprawić wydajność mnożenia bez poświęcania wydajności implementacji NumPy, bez budowania własnego mnożenia macierzy niskiego poziomu w c?
Ta metoda jest częścią optymalizacji numerycznej wielu zmiennych, a zatem O (N^3) jest trudny, natomiast O (N^2) prawdopodobnie wykona zadanie.
Dziękuję za pomoc. Ponadto, jestem nowy SO, więc proszę wybaczyć wszelkie błędy początkujących.
Czy brałeś pod uwagę 'cython' lub inny sposób kompilacji funkcji mnożenia bezpośrednio do kodu maszynowego? W dobrych czasach prawdopodobnie użyłbym 'f2py' do tego, ale wiem, że nie każdy chce pisać kod w fortran ;-) – mgilson
Nie jestem do końca pewien na ten temat, ale scipy może rozwiązać niektóre podobny problem z wykorzystaniem rzadkich macierzy. Czy wszyscy geniusze scipy wiedzą? – mgilson
Spójrz na 'scipy.sparse', Możesz uczynić' B' rzadką macierz 'B = scipy.sparse.csr_matrix (B)', a następnie po prostu wykonaj 'A * B', jeśli pomnóż gęstość przez rzadki wynik jest gęsty. Mam przeczucie, że jest to bardziej efektywne, ponieważ tego nie przetestowałem. – Akavall