Per quali metodi statistici le GPU sono più veloci delle CPU?


18

Ho appena installato una scheda grafica Nvidia GT660 sul mio desktop e, dopo qualche difficoltà, riesco a interfacciarlo con R.

Ho giocato con diversi pacchetti R che utilizzano GPU, in particolare gputools, e stavo confrontando il tempo impiegato dalla mia GPU e CPU per eseguire alcune operazioni di base:

  • invertire le matrici (CPU più veloce)
  • decomposizione qr (CPU più veloce)
  • grandi matrici di correlazione (CPU più veloce)
  • moltiplicazione matrice (GPU molto più veloce!)

Nota che ho sperimentato principalmente con gputools, quindi forse altri pacchetti funzionano meglio.

In termini generali, la mia domanda è: quali operazioni statistiche di routine che potrebbero valere la pena eseguire su una GPU anziché su una CPU?


1
Qualcosa che comporta molta moltiplicazione di matrice? :) Le GPU sono abbastanza popolari nella comunità delle reti neurali.

è necessario fornire le dimensioni delle matrici interessate. Ad esempio, l'ultima volta che ho verificato (ammesso 2 anni fa) l'inversione e la decomposizione erano solo più veloci sulla GPU a partire da grandi matrici (2 ^ 9 volte 2 ^ 9 e verso l'alto)
user189035

1
103×103

2
questa è un'ottima domanda, ma penso che otterrai risposte migliori
facendone

2
Il vantaggio della GPU rispetto alle normali CPU è il fatto che possono essere "massicciamente" parallele, non che sono più veloci per core. Come tale, per lavori che richiedono un sacco di "pulizie" come la fattorizzazione di Cholesky ecc. È necessario utilizzare algoritmi a blocchi e così via per ottenere una notevole accelerazione; questo non è banale e presumo ci vorrà un po 'prima che la GPU assuma tali operazioni. Ciò che sta sicuramente andando alla GPU è MCMC-ing (e generazione di numeri casuali). Il campionamento da un posteriore ha una "parallelizzazione" scritta dappertutto ... E calcoli di matrici sparse; sono già "bloccati" comunque ...
usεr11852 dice Reinstate Monic il

Risposte:


6

Le GPU sono bestie sensibili. Sebbene la scheda più beffa di Nvidia sia teoricamente in grado di eseguire qualsiasi operazione elencata 100 volte più veloce della CPU più veloce, circa un milione di cose possono ostacolare tale accelerazione. Ogni parte dell'algoritmo pertinente, e del programma che lo esegue, deve essere ampiamente ottimizzato e ottimizzato al fine di avvicinarsi a qualsiasi velocità teorica massima. R non è generalmente noto per essere un linguaggio particolarmente veloce, e quindi non mi sorprende che la sua implementazione di GPU predefinita non sia eccezionale, almeno in termini di prestazioni non elaborate. Tuttavia, le funzioni GPU R potrebbero avere impostazioni di ottimizzazione che è possibile modificare per recuperare alcune delle prestazioni mancanti.

Se stai esaminando le GPU perché hai scoperto che alcuni calcoli che devi eseguire impiegheranno settimane / mesi per terminare, potrebbe valere la pena passare da R a un linguaggio più performante. Python non è molto più difficile da lavorare rispetto a R. I pacchetti NumPy e SciPy hanno la maggior parte delle stesse funzioni stat di R, e PyCuda può essere usato per implementare le tue funzioni basate su GPU in un modo abbastanza semplice.

Se vuoi davvero aumentare la velocità con cui le tue funzioni funzionano su GPU, prenderei in considerazione l'implementazione delle tue funzioni in una combinazione di C ++ e CUDA. La libreria CUBLAS può essere utilizzata per gestire tutto il sollevamento pesante relativo all'algebra lineare. Tuttavia, tieni presente che può essere necessario un po 'di tempo per scrivere questo codice (soprattutto se è la prima volta che lo fai), e quindi questo approccio dovrebbe essere riservato solo per quei calcoli che richiedono tempi estremamente lunghi (mesi) e / o che ripeterai centinaia di volte.


6

In termini generali, gli algoritmi che funzionano più velocemente sulla GPU sono quelli in cui si sta eseguendo lo stesso tipo di istruzione su molti punti dati diversi.

Un semplice esempio per illustrare questo è con la moltiplicazione della matrice.

Supponiamo di fare il calcolo della matrice

UN×B=C

Un semplice algoritmo CPU potrebbe avere un aspetto simile

// a partire da 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];
            }
        }
    }
}

La cosa fondamentale da vedere qui è che ci sono molti cicli nidificati per i cicli e ogni passaggio deve essere eseguito uno dopo l'altro.

Vedi un diagramma di questo

Si noti che il calcolo di ciascun elemento di C non dipende da nessuno degli altri elementi. Quindi non importa in quale ordine vengono eseguiti i calcoli.

Quindi, sulla GPU, queste operazioni possono essere eseguite contemporaneamente.

Un kernel GPU per il calcolo di una moltiplicazione di matrici sarebbe simile

__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];
         }
     }
}

Questo kernel ha solo i due cicli interni. Un programma che invia questo lavoro alla GPU dirà alla GPU di eseguire questo kernel per ciascun punto dati in C. La GPU eseguirà ciascuna di queste istruzioni contemporaneamente su molti thread. Proprio come il vecchio detto "Più economico della dozzina" GPU sono progettate per essere più veloci facendo la stessa cosa molte volte.

Esistono tuttavia alcuni algoritmi che rallentano la GPU. Alcuni non sono adatti per la GPU.

Se per esempio ci fossero dipendenze dei dati, cioè: immagina che il calcolo di ciascun elemento di C dipendesse dagli elementi precedenti. Il programmatore dovrebbe mettere una barriera nel kernel per attendere il completamento di ogni calcolo precedente. Questo sarebbe un grande rallentamento.

Inoltre, algoritmi che hanno molta logica di ramificazione, ad esempio:

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

tendono a funzionare più lentamente sulla GPU perché la GPU non sta più facendo la stessa cosa in ogni thread.

Questa è una spiegazione semplificata perché ci sono molti altri fattori da considerare. Ad esempio, anche l'invio di dati tra CPU e GPU richiede tempo. A volte vale la pena fare un calcolo sulla GPU anche quando è più veloce sulla CPU, solo per evitare il tempo di invio aggiuntivo (e viceversa).

Anche molte CPU moderne supportano la concorrenza ora con processori multicore hyperthreaded.

Anche le GPU sembrano non essere così buone per la ricorsione, vedi qui che probabilmente spiega alcuni dei problemi con l'algoritmo QR. Credo che si abbiano alcune dipendenze ricorsive nei dati.


2
È ufficialmente malizioso SX commentare una risposta solo per dire che è una risposta formidabile, ma non do un perinæum di ratto sui negri: questa è una risposta deliziosa e istruttiva. Una delle grandi ingiustizie di SX è la mancanza di complimenti per le persone che danno risposte squisitamente informative su domande "vecchie" (nel tempo di Internet). (Inoltre, sto dando un pollice in su a una risposta "vecchia" (in tempo di Internet): lo so, vero? META).
GT.

Una considerazione importante è se esiste effettivamente una libreria per eseguire il calcolo: ad esempio, per quanto ne sappia, non ci sono implementazioni sparse x dense di GPU della moltiplicazione di matrici, certamente non attraverso pacchetti R. Se sei pronto a lavorare con la scrittura del codice GPU C, allora buona fortuna.
Jack Wasey,

4

n=210n,m210,K214

Più in generale, sospetto che la maggior parte delle operazioni statistiche che trascorrono la maggior parte del loro tempo in una densa algebra lineare (BLAS, funzionalità Lapack) possano essere implementate in modo efficiente sulla GPU.


0

Metodi di imputazione multipli per dati mancanti? Come quelli di Alice-II (R).

Penso che quelli tendano ad essere spesso imbarazzantemente paralleli e quindi adatti a un'architettura GPU. Non l'ho mai provato da solo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.