Dla jakich metod statystycznych procesory graficzne są szybsze niż procesory?

18

Właśnie zainstalowałem kartę graficzną Nvidia GT660 na pulpicie i po pewnym czasie udaje mi się połączyć ją z R.

Grałem z kilkoma pakietami R korzystającymi z GPU, szczególnie z gputools, i porównywałem czas, jaki mój procesor graficzny i procesor wykonywały podstawowe operacje:

  • odwracanie macierzy (szybszy procesor)
  • rozkład qr (szybszy procesor)
  • duże macierze korelacji (szybsze CPU)
  • mnożenie macierzy (GPU znacznie szybciej!)

Zauważ, że eksperymentowałem głównie z gputools, więc może inne pakiety działają lepiej.

Ogólnie rzecz biorąc, moje pytanie brzmi: jakie rutynowe operacje statystyczne mogą być warte wykonania na GPU, a nie na CPU?

Jugurtha
źródło
1
Coś związanego z mnożeniem macierzy? :) Procesory graficzne są dość popularne w społeczności sieci neuronowych.
musisz podać rozmiar macierzy. Na przykład ostatnio sprawdziłem (co prawda 2 lata temu) inwersja i rozkład były szybsze na GPU, poczynając od dużych macierzy (2 ^ 9 razy 2 ^ 9 i więcej)
użytkownik189035
1
Użyłem macierzy około do inwersji, qr i mnożenia macierzy, natomiast do korelacji zastosowałem około 10 ^ 4 obserwacji wektorów o wielkości 100. W przypadku inwersji macierzy GPU była znacznie wolniejsza, podczas gdy dla rozkładu qr była to wolniej, ale porównywalnie do procesora. 103)×103)
Jugurtha
2
to jest bardzo dobre pytanie, ale myślę, że uzyskasz lepsze odpowiedzi, migrując je do stackoverflow (myślę, że podobne pytania zostały już wcześniej zadane)
user189035
2
Zaletą GPU zwykłych procesorów jest to, że mogą one być „masowo” równoległe, a nie że są szybsze na rdzeń. Jako takie, w przypadku zadań, które wymagają dużo „sprzątania”, takich jak faktoryzacja Cholesky'ego itp., Musisz użyć algorytmów blokowych itp., Aby uzyskać znaczne przyspieszenie; nie jest to trywialne i zakładam, że zajmie to trochę czasu, zanim GPU przejmie takie operacje. To, co zdecydowanie idzie w kierunku GPU, to MCMC-ing (i generowanie liczb losowych). Próbkowanie z tyłu ma „równoległość” wypisaną na całym ... I rzadkie obliczenia macierzy; i tak są już „zablokowane” ...
usεr11852 mówi Przywróć Monic

Odpowiedzi:

6

GPU to wrażliwe bestie. Chociaż beefiest karta Nvidii teoretycznie może wykonać żadnej z wymienionych operacji ty 100x szybciej niż najszybszy CPU, o milion rzeczy może stanąć na drodze tej SpeedUp. Każda część odpowiedniego algorytmu i programu, który go uruchamia, musi zostać gruntownie zmodyfikowana i zoptymalizowana, aby zbliżyć się do teoretycznego maksymalnego przyspieszenia. R zwykle nie jest szczególnie szybkim językiem, więc nie dziwi mnie, że jego domyślna implementacja GPU nie jest tak świetna, przynajmniej pod względem surowej wydajności. Jednak funkcje R GPU mogą mieć ustawienia optymalizacji, które można dostosować, aby odzyskać część tej brakującej wydajności.

Jeśli zastanawiasz się nad układami GPU, ponieważ zauważyłeś, że wykonanie niektórych obliczeń zajmie tygodnie / miesiące, może warto poświęcić trochę czasu na migrację z języka R do języka bardziej sprzyjającego wydajności. W Pythonie nie jest o wiele trudniej pracować z R. Pakiety NumPy i SciPy mają większość takich samych funkcji statystycznych jak R, a PyCuda może być używany do implementacji własnych funkcji opartych na GPU w dość prosty sposób.

Jeśli naprawdę chcesz zwiększyć szybkość, z jaką Twoje funkcje działają na GPU, rozważę wdrożenie własnych funkcji w kombinacji C ++ i CUDA. Biblioteki CUBLAS można używać do obsługi wszystkich ciężkich operacji związanych z algebrą liniową. Pamiętaj jednak, że napisanie takiego kodu może zająć sporo czasu (zwłaszcza jeśli robisz to po raz pierwszy), dlatego takie podejście powinno być zarezerwowane tylko dla tych obliczeń, których uruchomienie zajmuje bardzo dużo czasu (miesiące) i / lub że będziesz powtarzać setki razy.

tel
źródło
6

Mówiąc ogólnie, algorytmy działające szybciej na GPU to takie, w których wykonuje się ten sam typ instrukcji w wielu różnych punktach danych.

Łatwym tego przykładem jest mnożenie macierzy.

Załóżmy, że wykonujemy obliczenia macierzowe

ZA×b=do

Prosty algorytm procesora może wyglądać podobnie

// zaczynając od C = 0

for (int i = 0; i < C_Width; i++)
{
    for (int j = 0; j < C_Height; j++)
    {
        for (int k = 0; k < A_Width; k++)
        {
            for (int l = 0; l < B_Height; l++)
            {
                C[j, i] += A[j, k] * B[l, i];
            }
        }
    }
}

Kluczową rzeczą do zobaczenia tutaj jest to, że istnieje wiele zagnieżdżonych pętli i każdy krok musi być wykonywany jeden po drugim.

Zobacz schemat tego

Zauważ, że obliczenie każdego elementu C nie zależy od żadnego z pozostałych elementów. Dlatego nie ma znaczenia, w jakiej kolejności są wykonywane obliczenia.

Na GPU operacje te można wykonywać jednocześnie.

Jądro GPU do obliczania mnożenia macierzy wyglądałoby mniej więcej tak

__kernel void Multiply
(
    __global float * A,
    __global float * B,
    __global float * C
)
{
     const int x = get_global_id(0);
     const int y = get_global_id(1);
     for (int k = 0; k < A_Width; k++)
     {
         for (int l = 0; l < B_Height; l++)
         {
             C[x, y] += A[x, k] * B[l, y];
         }
     }
}

To jądro ma tylko dwa wewnętrzne pętle for. Program wysyłający to zadanie do GPU nakazuje GPU wykonanie tego jądra dla każdego punktu danych w C. GPU wykona każdą z tych instrukcji jednocześnie na wielu wątkach. Podobnie jak w starym powiedzeniu „Tańsze o tuzin” procesory graficzne są zaprojektowane tak, aby szybciej robić to samo wiele razy.

Istnieją jednak pewne algorytmy, które spowalniają procesor graficzny. Niektóre nie są dobrze dostosowane do GPU.

Jeśli na przykład istniały zależności danych, tj .: wyobraź sobie, że obliczenia każdego elementu C zależą od poprzednich elementów. Programista musiałby umieścić barierę w jądrze, aby czekać na zakończenie każdego poprzedniego obliczenia. To byłoby poważne spowolnienie.

Ponadto algorytmy, które mają dużo logiki rozgałęziania, tj .:

__kernel Foo()
{
    if (somecondition)
    {
        do something
    }
    else
    {
        do something completely different
    }
}

zwykle działają wolniej na GPU, ponieważ GPU nie robi już tego samego w każdym wątku.

Jest to uproszczone wyjaśnienie, ponieważ należy wziąć pod uwagę wiele innych czynników. Na przykład wysyłanie danych między CPU a GPU jest również czasochłonne. Czasami warto wykonać obliczenia na GPU, nawet jeśli jest on szybszy na CPU, aby uniknąć dodatkowego czasu wysyłania (i odwrotnie).

Również wiele współczesnych procesorów obsługuje teraz współbieżność z wielordzeniowymi procesorami hiperwątkowymi.

Procesory graficzne również nie wydają się zbyt dobre do rekurencji, zobacz tutaj, co prawdopodobnie wyjaśnia niektóre problemy z algorytmem QR. Uważam, że ktoś ma pewne rekurencyjne zależności danych.

sav
źródło
2
Oficjalnie niegrzeczne jest SX komentowanie odpowiedzi tylko po to, aby powiedzieć, że jest to wspaniała odpowiedź, ale nie udzielam szczurom perinæum o negach: jest to zachwycająca i pouczająca odpowiedź. Jedną z największych niesprawiedliwości SX jest brak uznania dla ludzi, którzy udzielają niezwykle pouczających odpowiedzi na „stare” (w czasie internetowym) pytania. (Plus, daję aprobatę „starej” (w czasie Internetu) odpowiedzi: wiem, prawda? META).
GT.
Ważną kwestią jest to, czy rzeczywiście jest biblioteka do wykonywania obliczeń: np. O ile mi wiadomo, nie ma rzadkich x gęstych implementacji GPU mnożenia macierzy, z pewnością nie przez pakiety R. Jeśli jesteś przygotowany do pracy z pisaniem kodu GPU C, to powodzenia.
Jack Wasey
4

We wszystkich wymienionych aplikacjach procesory graficzne powinny być bardziej wydajne (z punktu widzenia sprzętowego) niż procesory w przypadku wystarczająco dużych matryc. Nic nie wiem na temat implementacji R. Ale z powodzeniem korzystałem z cuBLAS i Magmy przy inwersjachn=2)10 oraz mnożenie / korelacja dla macierzy prostokątnych z n,m2)10,k2)14. Szczególnie zaskakuje mnie, że duże macierze korelacji byłyby szybsze na procesorze korzystającym z R.

Mówiąc bardziej ogólnie, podejrzewam, że większość operacji statystycznych, które spędzają większość czasu w gęstej algebrze liniowej (BLAS, funkcjonalność Lapacka), można skutecznie zaimplementować na GPU.

Max Hutchinson
źródło
0

Wiele metod imputacji brakujących danych? Podobnie jak w Alice-II (R).

Myślę, że są one często kłopotliwie równoległe i dlatego nadają się do architektury GPU. Nigdy sam tego nie próbowałem.

ciekawy kot
źródło