Nella programmazione del software, sarebbe possibile avere carichi CPU e GPU al 100%?

43

Questa è una domanda generale su un argomento che ho trovato interessante come giocatore: colli di bottiglia CPU / GPU e programmazione. Se non sbaglio, ho capito che sia la CPU che la GPU calcolano le cose, ma quella è migliore in alcuni calcoli rispetto all'altra a causa della differenza di architettura. Ad esempio, cracking hashes o criptovaluta mining sembra molto più efficiente su GPU che su CPU.

Quindi mi sono chiesto: sta avendo una GPU al 100% di carico mentre la CPU è al 50% (ad esempio) inevitabile?

O, più precisamente: Alcuni calcoli che vengono normalmente eseguiti dalla GPU possono essere eseguiti dalla CPU se il primo è al 100% di carico, in modo che entrambi raggiungano il 100% del carico?

Ho cercato un po 'sull'argomento, ma sono tornato abbastanza a mani vuote. Penso e spero che questo abbia il suo posto in questa sottosezione e sono aperto a qualsiasi documentazione o lezione che potresti darmi!

    
posta MadWard 24.06.2016 - 11:06
fonte

7 risposte

62

Teoricamente sì, ma in pratica raramente ne vale la pena.

Sia le CPU che le GPU sono turing-complete , quindi qualsiasi algoritmo che può essere calcolato da uno può anche essere calcolato da l'altro. La domanda è quanto veloce e quanto conveniente.

Mentre la GPU eccelle nel fare gli stessi semplici calcoli su molti data-point di un grande set di dati, la CPU è migliore per algoritmi più complessi con molte ramificazioni. Con la maggior parte dei problemi, la differenza di prestazioni tra le implementazioni della CPU e della GPU è enorme. Ciò significa che l'utilizzo di uno per rimuovere il lavoro dall'altro quando è in fase di stallo non porterà a un notevole aumento delle prestazioni.

Tuttavia, il prezzo da pagare per questo è che è necessario programmare tutto due volte, una volta per la CPU e una volta per la GPU. Questo è più del doppio del lavoro perché dovrai anche implementare la logica di commutazione e sincronizzazione. Questa logica è estremamente difficile da testare, perché il suo comportamento dipende dal carico corrente. Aspettatevi molto oscuri e impossibili da riprodurre bug da questa acrobazia.

    
risposta data 24.06.2016 - 11:14
fonte
36

Non è legato alla programmazione del gioco. Alcuni codici scientifici possono anche utilizzare sia la GPU che la CPU.

Con una programmazione attenta e dolorosa, ad es. utilizzando OpenCL o CUDA , potresti caricare sia la tua GPU che la tua CPU vicino al 100%. Molto probabilmente avrai bisogno di scrivere diversi pezzi di codice per la GPU (il cosiddetto codice "kernel") e per la CPU, e qualche codice di colla noioso (in particolare per inviare alla GPU il codice del kernel compilato).

Tuttavia, il codice sarebbe complesso e probabilmente è necessario sintonizzarlo sull'hardware specifico su cui si sta eseguendo, in particolare perché la trasmissione dei dati tra GPU e amp; La CPU è costosa.

Ulteriori informazioni su calcolo eterogeneo .

Vedi anche OpenACC , supportato dalle recenti versioni di GCC (ad esempio GCC 6 nel giugno 2016)

    
risposta data 24.06.2016 - 11:11
fonte
11

Da un punto di vista del supercomputing è meglio non pensare in termini di carico CPU / GPU in percentuale, ma piuttosto determinare quante operazioni il tuo problema ha bisogno e poi confrontarlo con le prestazioni di punta del sistema.

Se si ottiene il 100% di utilizzo della CPU, non significa necessariamente che si ottengano tutte le prestazioni dal sistema. Le CPU possono spesso fare più cose nello stesso momento, ad esempio una divisione e un'aggiunta. Se è possibile avviare la divisione in anticipo, è possibile che si sovrapponga all'aggiunta. Molto probabilmente la tua CPU desktop ha un'unità fuori uso che riorganizzerà le istruzioni per trarre vantaggio da tali sovrapposizioni. O se hai il seguente programma:

if (expr1)
    expr2;
else
    expr3;

Una CPU di riordino proverà a calcolare le tre espressioni allo stesso tempo e quindi a buttare via il risultato di una di esse. Questo lo rende più veloce nel complesso. Se hai qualche blocco nel tuo programma e non puoi riordinare, allora stai utilizzando meno corsie nella CPU, ma probabilmente mostrerà ancora il 100%.

Poi hai le funzionalità SIMD nelle CPU che sono operazioni vettoriali. È come la GPGPU-light, nel senso che di solito hai solo quattro o otto operazioni allo stesso tempo, le GPU piacciono 32 o 64. Comunque devi usarlo per tirare fuori il FLOPS.

Stuff come la condivisione falsa può portare a un costo di sincronizzazione pesante che di solito si presenta come carico del kernel in Linux. La CPU è completamente utilizzata ma non hai un throughput molto utile.

Ho fatto qualche programmazione su una macchina IBM Blue Gene / Q. Ha molti livelli di gerarchia ( schema di Blue Gene / L obsoleto) ed è quindi difficile da programmare in modo efficiente. Dovrai utilizzare la gerarchia completa fino a SIMD e SMT (Intel chiama questo HyperThreading) per ottenere le prestazioni.

E poi la rete ti limita spesso. Pertanto risulta che è più veloce in (wall clock) il tempo di calcolare le cose su più CPU allo stesso tempo invece di comunicarlo attraverso la rete. Questo caricherà più carico sulle CPU e farà accelerare il programma. Ma il throughput effettivo del programma non è buono come sembra dai numeri grezzi.

Se aggiungi GPU al mix, diventerà ancora più difficile orchestrare tutto questo per ottenere prestazioni. Questa sarà una delle cose che comincerò a fare nella mia tesi di laurea di QC su Lattice tra un paio di mesi.

    
risposta data 24.06.2016 - 16:02
fonte
1

Potresti essere interessato a verificare il servo motore di navigazione sviluppato in Mozilla Research, e in particolare Web Render (video) .

Sebbene spostare dinamicamente un'attività dalla CPU alla GPU potrebbe essere poco pratico, come menzionato in altre risposte (in particolare @ Philip's), può essere pratico studiare in anticipo il carico di CPU / GPU sui carichi di lavoro tipici e passare alcuni attività a quella generalmente meno caricata.

Nel caso di Web Render, la novità è che tradizionalmente i browser eseguono la maggior parte del loro lavoro di rendering sulla CPU (cioè, la CPU viene utilizzata per calcolare quali oggetti visualizzare, dove tagliare, ecc ...). Normalmente la GPU è meglio ... tranne che non tutti gli usi sono banali da implementare (abbandono parziale, ombre, ... e testo).

Una versione iniziale di Web Render si è dimostrata di grande successo nell'aumento delle prestazioni, ma non ha provato a risolvere il problema del rendering del testo (e aveva alcune altre limitazioni). Mozilla Research sta ora lavorando su una seconda versione che ha lo scopo di avere meno limitazioni, e in particolare per supportare il rendering del testo.

L'obiettivo, naturalmente, è di scaricare il più possibile il processo di rendering nella GPU, lasciando la CPU libera di eseguire Javascript, aggiornare il DOM e tutte le altre attività.

Quindi, sebbene non sia così estremo come il tuo suggerimento, va nella direzione di progettare una strategia di calcolo con in mente entrambi CPU e GPU.

    
risposta data 24.06.2016 - 17:10
fonte
0

Concentrandoti sui giochi (poiché lo hai menzionato specificamente nel tuo post), ci sono alcuni modi in cui puoi bilanciare il carico. Un esempio è "skinning", ovvero l'animazione di un modello. Per ogni fotogramma da renderizzare, devi generare le matrici di trasformazione per ciascun fotogramma dell'animazione e applicarlo ai vertici del modello per trasformarlo nella posizione in cui deve essere inserito. Devi anche interpolare i fotogrammi per ottenere un movimento fluido , a meno che tu non voglia che l'animazione assomigli al Quake originale (cioè a scatti).

In questa situazione, puoi farlo sulla CPU e caricare i risultati nella GPU per il rendering, o eseguire il calcolo e il rendering sulla GPU. Credo che oggigiorno sia fatto sulla GPU (noto come "skinning dell'hardware"): ha senso farlo in quanto hai calcoli relativamente semplici che devono essere eseguiti migliaia di volte e ogni vertice può essere calcolato contemporaneamente dal risultato del vertice A non ha alcuna relazione con il risultato del vertice B.

In teoria, tuttavia, potresti passare dinamicamente dal farlo sulla CPU o sulla GPU a seconda di quanto siano sovraccariche la GPU e la CPU.

Il blocco principale per fare questo attraverso tutti i calcoli è che CPU e GPU hanno punti di forza e debolezze diversi. I lavori in parallelo massivo vengono eseguiti meglio sulla GPU, mentre le attività lineari intensive con ramificazioni vengono eseguite meglio sulla CPU. Solo pochi lavori potrebbero essere fatti realisticamente su entrambi, senza un grave calo delle prestazioni.

Nel complesso, il problema principale con la programmazione della GPU (almeno con OpenGL e DirectX 11 e sotto) è che hai poco controllo su come la GPU interpreta il tuo codice shader. Ramificarsi all'interno di uno shader è rischioso perché se si crea accidentalmente una dipendenza tra i calcoli, la GPU potrebbe decidere di avviare il rendering dei pixel uno per uno, trasformando 60 fps in 10 fps in un istante nonostante i dati reali da rendere identici.

    
risposta data 24.06.2016 - 14:32
fonte
0

Un esempio del mondo reale è il motore di rendering open source LuxRender , che è in grado di caricare completamente una CPU e una GPU a lo stesso tempo. Inoltre, può caricare più GPU contemporaneamente e può anche distribuire su più computer.

LuxRender usa OpenCL per facilitare questo, anche se esistono build senza OpenCL.

Questo è pratico perché gli algoritmi utilizzati da LuxRender sono altamente parallelizzabili. L'algoritmo più comune utilizzato da LuxRender è tracciamento del percorso , in cui molti percorsi di luce individuali possono essere calcolati indipendentemente l'uno dall'altro: una situazione ideale per GPU computing e uno che non richiede alcuna sincronizzazione complessa tra i nodi di calcolo. Tuttavia, le limitazioni delle GPU (minori quantità di memoria, mancanza di supporto per alcune funzioni di rendering complesse e mancanza generale di disponibilità per alcuni artisti) assicurano che il supporto della CPU sia ancora essenziale.

    
risposta data 26.06.2016 - 00:18
fonte
0

Sì, è certamente possibile.

Qualsiasi calcolo che una CPU può fare, anche una GPU può fare, e viceversa.

Ma non è comune perché:

  • Complessità ingegneristica Sebbene sia possibile eseguire lo stesso codice su CPU e GPU (ad esempio CUDA), i processori hanno caratteristiche e prestazioni diverse. Uno è MIMD; l'altro, SIMD. Ciò che è veloce su uno è lento sull'altro (ad es. Ramificazione), quindi è necessario scrivere codice separato per massimizzare le prestazioni.

  • L'efficienza dei costi le GPU sono in aggregato molto più potenti delle CPU. L'idea generale delle GPU è quella di utilizzare processori più economici, più lenti, ma più numerosi per eseguire calcoli molto più velocemente di quanto potrebbero fare le CPU allo stesso costo. Le GPU sono più efficienti in termini di costi di uno o due ordini di grandezza.

Se il tuo algoritmo viene eseguito su GPU, è più sensato ottimizzarlo e aggiungerne il numero necessario.

    
risposta data 26.06.2016 - 20:45
fonte

Leggi altre domande sui tag