2016-05-18 31 views
6

Jest to kod pisałem:Przyspieszenie mnożenia macierzy za pomocą OpenMP i metody blokowej: czy mogę zrobić lepiej?

#include <omp.h> 
void matrix_multi(int c[][TSIZE], int a[][TSIZE], int b[][TSIZE]) 
{ 
    int B=8; 

    int i, j, k,i1,j1,k1; 
#pragma omp parallel for private(i,j,k,i1,j1,k1) schedule(auto) collapse(3) 
    for (i=0; i<TSIZE; i+=B) 
    for (j=0; j<TSIZE; j+=B) 
     for (k=0; k<TSIZE; k+=B) 
     for (i1=i;i1<i+B;i1++) 
      for (j1=j;j1<j+B;j1++) 
      { 
       int sum=0; 
       for (k1=k;k1<k+B;k1++) 
       { 
        sum+=a[i1][k1]*b[k1][j1]; 
       } 
       c[i1][j1]+=sum; 
      } 

} 

Moje pytanie brzmi: Czy mogę uzyskać lepszą wydajność przy jakiejś dalszej manipulacji na trzech wewnętrznych pętli?

+0

Czy zmierzyłeś się z osiągnięciami? Mnożenie macierzy można porównać z teoretyczną wydajnością szczytową. – Zulan

+0

Nie jestem przekonany, czy ten kod jest poprawny: dyrektywa 'collapse (3)' jest równoległa do 3 indeksów 'i',' j' i 'k'. Oznacza to, że masz zagwarantowane, że żadne identyczne tryplety 'i, j, k' nie będą obsługiwane przez dwa różne wątki. Można jednak bardzo dobrze mieć tę samą parę "i, j" z innym k dla dwóch wątków. A to doprowadzi do stanu wyścigowego do aktualizacji 'c [i1] [j1]' ... – Gilles

+0

[Ten konkretny film z kursu] (http://ocw.mit.edu/courses/electrical-engineering-and-computer- science/6-172-performance-engineering-of-software-systems-fall-2010/video-wykłady/wykład-1-matrix-multiply-a-case-study /) w całości poświęcony jest poprawie szybkości mnożenia macierzy. – displayName

Odpowiedz

3

Algebra liniowa jest jedną z najczęściej wykonywanych operacji komputerowych. W grach i bibliotekach graficznych jest to najczęstsza operacja. Został on dokładnie zbadany i zoptymalizowany, a całe grupy badawcze go poświęciły.

Jeśli zależy Ci na szybkości, powinieneś wykonywać mnożenie macierzy przy pomocy biblioteki BLAS. Niektóre z rzeczy, które biblioteka BLAS będzie optymalizować dla:

  • zminimalizować Cache-tęskni wykonując mnożenia macierzy w blokach zamiast pętli na całej matrycy
  • zoptymalizować wielkość bloku dla cache-size z komputer
  • jeśli komputer/procesor ma wiele poziomów cache, używać wielu zoptymalizowane poziomy rozmiar bloku
  • korzystanie SIMD instrukcje jeśli jest dostępny na CPU

Należy zauważyć, że równoległość nie znajduje się na liście. Dzieje się tak, ponieważ w dzisiejszych komputerach dostęp do pamięci jest wolniejszy niż procesor. Zobaczysz gorzej wydajność z openmp ze względu na obciążenie przełączania kontekstu.

1

Wygląda na to, że jesteś daleko od pełnej optymalizacji. Czy próbowałeś rozwinąć pętlę, inwersję pętli itp.?

Możesz odwołać się do poniższego linku, aby uzyskać optymalizację krok po kroku dla mnożenia macierzy.

http://wiki.cs.utexas.edu/rvdg/HowToOptimizeGemm/

+0

Studiowałem to przez jeden dzień i przeprowadziłem wiele eksperymentów. Niestety, myślę, że to jest trudne (lub z moich możliwości) do wykorzystania openMP w tej metodzie. Działa nieco gorzej niż kod z openMP. –

+0

@HuanmingSong Łącze optymalizuje jeden wątek GEMM. Dzięki zoptymalizowanemu jednemu wątkowi GEMM można następnie użyć OpenMP, aby poprawić wydajność wielordzeniowych procesorów. – kangshiyin