Problem z tym przykładem polega na tym, że działa on tylko dla macierzy kwadratowych. Jeśli macierze nie są kwadratowe, nie można obliczyć wartości A^t*B^t
z powodu wymiaru missmatch (zakładając, że wymiary były odpowiednie dla A*B
).
Nie mam działającej instalacji cuBLAS pod ręką, więc to rodzaj strzału w ciemności, ale byłbym naprawdę zaskoczony, gdyby cuBLAS działałby inaczej niż zwykły BLAS. BLAS spodziewa się, że macierze będą w kolumnie największego rzędu (również w kolejności Fortran), ale mogą być również używane dla macierzy w rzędzie-wyższym rzędzie (zwanym również zamówieniem C).
Moim zdaniem, co może być całkowicie błędne, gemm_v2
nie jest zwykłym/najlepszym sposobem na poradzenie sobie z mnożeniem dwóch macierzy C-rzędowych, na przykład dlatego, że jeśli mnoży się dwie macierze rzędu C, to można również uzyskać C- uporządkuj matrycę jako odpowiedź.
Sztuką obliczyć iloczyn dwóch C-order-macierzy przy pomocy gemm
będzie działać w następujący sposób:
Nawet jeśli jest to zapewne znana wam, chciałbym najpierw opracować na wiersz poważnych porządek (układ c-pamięci) i kolumna-główny-porządek (układ fortran-memory), aby rozwinąć moją odpowiedź.
Więc jeśli mamy 2x3
(tzn 2 rzędy i 3 kolumny) macierzy A
i przechowywać go w jakiejś ciągłej pamięci otrzymujemy:
row-major-order(A) = A11, A12, A13, A21, A22, A23
col-major-order(A) = A11, A21, A12, A22, A13, A33
Oznacza to, że jeśli mamy ciągłą pamięć, co oznacza macierz w rzędzie-wyższym rzędzie, i interpretujcie to jak macierz w kolumnie-major-rozkazie dostaniemy zupełnie inną macierz!
Jednak jeśli spojrzymy na transponowana macierz A^t
możemy łatwo zobaczyć:
row-major-order(A) = col-major-order(A^t)
col-major-order(A) = row-major-order(A^t)
Oznacza to, że jeśli chcielibyśmy uzyskać macierz C
w row-major-order jako konsekwencji blas-procedura powinna zapisywać transponowaną matrycę C
w kolumnie-głównym porządku (po tym wszystkim, czego nie możemy zmienić) do tej właśnie pamięci. Jednakże, C^t=(AB)^t=B^t*A^t
i B^t
an A^t
są oryginalnymi macierzami ponownie zinterpretowanymi w kolumnie głównej.
Teraz A
być n x k
-Matrix i B
k x m
-Matrix, wezwanie gemm rutyny powinna być następująca:
gemm('N', 'N', m, n, k, 1.0, B, m, A, k, 0.0, C, m)
Uwaga:
- My nie Muszą przetransponować macierze
A
i B
, ponieważ jest to obsługiwane przez ponowne interpretowanie C-order jako Fortran-order.
- Musimy zamienić miejsca macierzy
A
i B
, aby uzyskać C^t
w kolejności Fortran jako wynik.
- Wynikowa macierz
C
jest w porządku C (reinterpretując ją od Fortran-order do C-order pozbywamy się ^t
).
w wezwaniu do blas, określasz gemm (transa, transb, m, n, k, alfa, A: r, B: r, beta, C: w); gdzie transa i transb są operacjami, które należy zastosować do macierzy. W przykładzie gemm_v1 jest to operacja tożsamości, w przykładzie gemm_v2 jest to transpozycja. Następnie podaj m, n i k. Są to # pola A (m), # kolumny rzędów A/# B (n) i kolumny B (k). Jeśli utrzymasz go w składni przykładu, określisz go jako macierz z kwadratem, więc to jest miejsce, w którym można to zmienić. Upewnij się, że kształt twoich matryc jest zgodny z deklaracją. – Uvar