2016-06-01 14 views
7

Sulla mia macchina ho due famiglie di code, una che supporta tutto e una che supporta solo il trasferimento.Dovrei provare ad usare quante più code possibile?

La famiglia di code che supporta tutto ha un queueCount di 16.

Ora gli stati spec

buffer di comando sottoposte diverse code possono essere eseguiti in parallelo o addirittura fuori uso l'uno rispetto all'altro

Vuol dire che dovrei provare ad usare tutti disponibili code per le massime prestazioni?

risposta

10

Sì, se si dispone di un carico di lavoro altamente indipendente, utilizzare code separate.

Se le code necessitano di molta sincronizzazione tra loro, possono eliminare tutti i potenziali benefici che si possono ottenere.

Fondamentalmente ciò che si sta facendo è fornire alla GPU un lavoro alternativo che può fare (e riempire bancarelle e bolle e rilasciare e dare a GPU la scelta) nel caso della stessa famiglia di code. E c'è del potenziale per usare meglio la CPU (ad esempio singlethreaded vs una coda per thread).

L'utilizzo di code di trasferimento separate (o altre famiglie specializzate) sembra essere l'approccio consigliato anche.

In linea generale. Una visione più realistica, empirica, scettica e pratica era già stata presentata dalle risposte SW e NB.

+2

È vero. Se stai facendo molti trasferimenti (ad esempio, i buffer di staging), specialmente in fase di esecuzione, si consiglia di utilizzare una coda di trasferimento dedicata. Con i driver recenti, le GPU NVIDIA e AMD dovrebbero offrire alle famiglie di code solo trasferimenti di supporto (o primari). –

+1

Dovrebbe? Pensavo che lo avessero già fatto. Almeno AMD da tempo i beta driver ... E penso di averlo tratto da alcuni discorsi di NVIDIA. – krOoze

+2

"* Sì, pensateli come core della CPU in questo senso. *" Penso che l'analogia, per le code della stessa famiglia, dia un'impressione sbagliata. Sembra che, se una GPU fornisce 16 core grafici separati e stai solo inviando il lavoro a 1 di loro, allora stai usando solo 1/16 dell'hardware della tua GPU. Sembra decisamente improbabile. Per le code di * diverse * famiglie, questa analogia ha senso. Rappresentano hardware distinto. Le code all'interno della stessa famiglia non necessariamente lo fanno. –

5

Ciò dipende in gran parte dallo scenario e dall'impostazione effettivi. È difficile dirlo senza dettagli.

Se si inoltrano buffer di comando a più code, è inoltre necessario eseguire la sincronizzazione corretta e, se ciò non viene eseguito correttamente, è possibile ottenere prestazioni peggiori rispetto all'uso di una sola coda.

Si noti che anche se si invia a una sola coda un'implementazione può eseguire buffer di comando in parallelo e persino fuori ordine (ovvero "in-flight"), vedere i dettagli al riguardo nel capitolo chapter 2.2 of the specs o this AMD presentation.

Se si esegue il calcolo e la grafica, l'utilizzo di code separate con invii simultanei (e una sincronizzazione) migliorerà le prestazioni su hardware che supporta il calcolo asincrono.

Quindi non esiste un sì o un no definitivo senza conoscere il vostro caso d'uso effettivo.

10

A che scopo?

Prendere la struttura tipica di un renderer posticipato. Costruisci i tuoi g-buffer, fai i tuoi passaggi di luce, fai un po 'di post-processing e tone mapping, magari getta delle cose trasparenti e poi presenti l'immagine finale. Ogni processo dipende dal completamento del processo precedente prima che possa iniziare. Non puoi passare l'illuminazione finché non hai finito il tuo g-buffer. E così via.

Come si può parallelizzare su più code di esecuzione? Non è possibile parallelizzare l'edificio g-buffer o i passaggi di illuminazione, poiché tutti questi comandi scrivono sulle stesse immagini allegate (e non è possibile farlo da più code). E se non stanno scrivendo le stesse immagini, allora dovrai scegliere una coda in cui combinare le immagini risultanti in quella finale. Inoltre, non ho idea di come funzioni il buffer di profondità senza utilizzare lo stesso buffer di profondità.

E quella combinazione avrebbe richiesto la sincronizzazione.

Ora, ci sono molte attività che possono essere parallele. Facendo macinare il frustum. Aggiornamenti del sistema di particelle. Trasferimenti di memoria Cose così; dati che sono destinati al successivo frame. Ma quante code potresti realisticamente tenere occupate in una volta? 3? Forse 4?

Per non parlare del fatto che è necessario creare un sistema di rendering che possa scalare. Vulkan non richiede che le implementazioni forniscano più di una coda. Quindi il tuo codice deve essere in grado di funzionare ragionevolmente su un sistema che offre solo una coda e un sistema che offre 16. E per trarre vantaggio da un sistema a 16 code, potrebbe essere necessario eseguire il rendering in modo molto diverso.

Oh, e si tenga presente che se si richiedono un sacco di code, ma non lo si utilizza , il rendimento potrebbe essere influenzato. Se si richiedono 8 code, l'implementazione non ha altra scelta che presumere che si intende essere in grado di emettere 8 serie di comandi simultanei. Ciò significa che l'hardware non può dedicare tutte le sue risorse a una singola coda. Pertanto, se utilizzi solo 3 di essi ... potresti perdere oltre il 50% delle tue prestazioni potenziali in risorse che l'implementazione è in attesa di utilizzare.

Concesso, l'implementazione potrebbe ridimensionare queste cose in modo dinamico. Ma a meno che non profili questo caso particolare, non lo saprai mai. Oh, e se scala dinamicamente ... allora non sarai guadagnando un sacco da usare più code come questa.

+0

Sei a conoscenza di un dispositivo in cui la richiesta di code, ma non l'uso, ha gravi ripercussioni sulle prestazioni? Mi sembra che, se questo fosse vero, dovresti sempre usare solo una coda, a meno che tu non possa tenere occupate più code in ogni momento. – Quinchilion