Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi
Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi
Mate X7 rinnova la sfida nel segmento dei pieghevoli premium puntando su un design ancora più sottile e resistente, unito al ritorno dei processori proprietari della serie Kirin. L'assenza dei servizi Google e del 5G pesa ancora sull'esperienza utente, ma il comparto fotografico e la qualità costruttiva cercano di compensare queste mancanze strutturali con soluzioni ingegneristiche di altissimo livello
Nioh 3: souls-like punitivo e Action RPG
Nioh 3: souls-like punitivo e Action RPG
Nioh 3 aggiorna la formula Team NINJA con aree esplorabili più grandi, due stili di combattimento intercambiabili al volo (Samurai e Ninja) e un sistema di progressione pieno di attività, basi nemiche e sfide legate al Crogiolo. La recensione entra nel dettaglio su combattimento, build, progressione e requisiti PC
Test in super anteprima di Navimow i220 LiDAR: il robot tagliaerba per tutti
Test in super anteprima di Navimow i220 LiDAR: il robot tagliaerba per tutti
La facilità di installazione e la completa automazione di tutte le fasi di utilizzo, rendono questo prodotto l'ideale per molti clienti. Ecco com'è andata la nostra prova in anteprima
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 28-08-2010, 12:16   #1
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
[CUDA C] Instruzioni atomiche

Ciao a tutti, mi sono appena iscritto anche se è da un po che leggo su questo forum.
Sto scrivendo una piccola applicazione in CUDA per Windows 7, l'ambiente di sviluppo è Visual C++ 2008. Ho ancora le idee un po confuse su CUDA infatti sto incontrando alcune difficoltà nella stesura del codice del Kernel: devo fare in modo che ciascun thread, appartenente ad un blocco, aggiunga un valore ad un valore precedente memorizzato in una variabile allocata nella device memory. Ovviamente l'operazione deve essere fatta sequenzialmente per permettere a un thread di leggere l'incremento fatto precedemente da un altro thread. Per questo motivo ho la necessità di utilizzare un'istruzione atomica. E qui arriva il bello

In un normale programma il codice è cosi:

Codice:
for(i = 0; i < N; i++)
{
        n = n + punti[i].z * peso;
	d = d + peso;
}

if (n != 0.0) {
        r = n / d;
        g->peso = r * pow(livelli[l].scala, 2);
}
else g->peso = 0.0;

Non riesco a capire come posso scrivere quelle due righe di codice nel ciclo for per fare in modo che ogni thread possa sommare un valore al valore esistente.
Il mio tentativo è stato quello di usare la funzione "atomicAdd()" in questo modo:

codice kernel:
Codice:
int i = blockDim.x * blockIdx.x + threadIdx.x;

atomicAdd(&n, punti[i].z * peso);
atomicAdd(&d, peso);

__syncthreads();

if (n != 0.0) {
	r = n / d;
	g->peso = r * pow(livelli[l].scala, 2);
}
else g->peso = 0.0;
ma a questo punto il compilatore mi da errore: "identifier "atomicAdd" is undefined"
Devo aggiungere qualche altra libreria??
Avete qualche altro suggerimento su come potrei fare eseguire quelle istruzioni?

Poi ho un altro dubbio sempre sul codice del kernel che ho riportato: come posso fare in modo che il codice dopo alla funzione "__syncthreads();" venga eseguito da 1 solo thread al termine di tutta la computazione??

L'hardware che ho a disposizione è una NVIDIA GT230M compute capability 1.2.

Grazie in anticipo!
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 28-08-2010, 13:32   #2
Tommo
Senior Member
 
L'Avatar di Tommo
 
Iscritto dal: Feb 2006
Messaggi: 1304
devi includere nel sorgente CUDA l'header che definisce le atomics, non mi ricordo qual'è.

Per far eseguire il codice ad un solo thread è facile, basta fare
Quote:
if( i == n )
E lo eseguirà solo il thread n.

Purtroppo per te il bello arriva ora, perchè ti accorgerai che la GPU andrà più lenta della CPU
E probabilmente anche di diverse volte.

I thread della GPU presi singolarmente sono decisamente "deboli" (nell'hardware non sono nemmeno veri threads) e la serializzazione porta al completo sconvolgimento della pipeline.
Serializzare OGNI thread con TUTTI quelli precedenti porta al blocco completo.

L'unico modo che hai di andare veramente veloce è dimenticarti delle atomics e trovare un modo di fare la stessa cosa leggendo meno dati possibili dalla memoria, meno che meno dagli altri threads.
Così com'è ora fai meglio a lasciar stare.
__________________
*ToMmO*

devlog | twitter
Tommo è offline   Rispondi citando il messaggio o parte di esso
Old 28-08-2010, 14:24   #3
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Innanzitutto grazie per la risposta!
Ho capito è meglio evitare di usare le funzioni atomiche, in effetti è un po un controsenso usare un'architettura per lavorare in parallelo e poi fargli eseguire delle operazioni in serie.
Praticamente mi suggerisci di fare eseguire quella parte di codice sulla CPU? Posso fare cosi, mi semplificherebbe molto la vita, il fatto è che quelle due istruzioni, in particolare nell'ultimo passo dell'algoritmo, devono essere eseguite circa 260 milioni di volte e non era male se riuscivo a passare il carico di lavoro sulla GPU.

Ho pensato a una soluzione alternativa di questo tipo:

Codice:
int i = blockDim.x * blockIdx.x + threadIdx.x;

peso = .................
n[i] = punti[i].z * peso;
d[i] = peso;

__syncthreads();
Ogni thread di un blocco inserisce un valore in un vettore ("n" e "d") allocati nella shared memory. Quando tutti i thread hanno finito, eseguo la somma di tutti i valori del vettore sfruttando uno o più thread. Però in questo caso il problema è che i vettori "n" e "d" saranno visibili solo ai thread che appartengono ad un solo blocco....se io necessito di più blocchi per portare a termine l'operazione come posso fare?
Che ne pensate? Vi sembra una soluzione fattibile?

Qualsiasi idea o suggerimento è bene accetto
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 28-08-2010, 17:20   #4
Tommo
Senior Member
 
L'Avatar di Tommo
 
Iscritto dal: Feb 2006
Messaggi: 1304
Beh io ho detto il caso estremo, però in realtà operazioni seriali le puoi anche fare

Di solito si parte risolvendo tutto nella shared memory; poi si accumula il valore in un registro che viene riversato nella memoria globale. A quel punto un blocco copia tutti questi valori dalla memoria globale nella sua shared memory e li accumula a loro volta, finchè non rimane uno solo.
Sembra facile (o anche no), ma ci sono tantissime ottimizzazioni possibili, tipo sul numero di registri, sui bank conflicts, etc...

Prova a vedere i vari algoritmi di "gather", sul forum di CUDA ce ne sono tantissimi decisamente ottimizzati, che fanno un sacco di roba tra cui la somma di array che serve a te.
__________________
*ToMmO*

devlog | twitter
Tommo è offline   Rispondi citando il messaggio o parte di esso
Old 01-09-2010, 20:35   #5
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Ciao!

Ho cercato sul forum di CUDA come mi hai suggerito e ho trovato molto materiale davvero interessante, in particolare gli algoritmi di riduzione che effettuano appunto le somme che servono a me. Sono riuscito ad applicarne uno con diverse ottimizzazioni.

Grazie mille per i suggerimenti! Credo che in futuro ritornerò a chiedere consigli
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 01-09-2010, 22:54   #6
marco.r
Senior Member
 
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
Procedendo nel modo che proponi non ottieni nulla dei vantaggi della computazione su GPU, fai prima ad eseguire du CPU che almeno ti risparmi il passaggio dei valor dall'altra.
La reduce o fold di un vettore, in una architettura parallela, va fatto in modo totalmente diverso (e piu'complicato), perche' prevede una sorta di approccio divide et impera sul vettore da sommare e che permette di eseguire l'operazione (nel caso naive) in tempo log(n). Se cerchi su internet ci sono un paio di paper di nvidia a riguardo.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele
marco.r è offline   Rispondi citando il messaggio o parte di esso
Old 02-09-2010, 01:39   #7
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Come ho già scritto sopra ho applicato un algoritmo di reduce basato su balanced trees che ha complessità O(n).
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 02-09-2010, 09:46   #8
marco.r
Senior Member
 
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
Quote:
Originariamente inviato da HRBF Guarda i messaggi
Come ho già scritto sopra ho applicato un algoritmo di reduce basato su balanced trees che ha complessità O(n).
uhm, ma se ha complessita' O(n) che vantaggio hai ?
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele
marco.r è offline   Rispondi citando il messaggio o parte di esso
Old 02-09-2010, 11:43   #9
Tommo
Senior Member
 
L'Avatar di Tommo
 
Iscritto dal: Feb 2006
Messaggi: 1304
La GPU ha la capacità di eseguire algoritmi O(n) in circa O(1)
Lo scopo è creare un algoritmo O(n) dove ogni elemento ha il suo thread...
__________________
*ToMmO*

devlog | twitter
Tommo è offline   Rispondi citando il messaggio o parte di esso
Old 02-09-2010, 14:03   #10
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Esattamente... la complessità è come quella di un algoritmo sequenziale che gira su CPU, ma c'è il vantaggio della computazione in parallelo eseguita da "n" thread.
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 30-09-2010, 14:59   #11
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Ciao a tutti, rispolvero questo thread per chiedere un aiuto: ho la necessità di usare l'istruzione atomica "atomicInc()" in un kernel.
Ho letto che il compilatore nvcc compila di default con il comando "-arch sm_10" cioè utilizza la compute capability 1.0. Per utilizzare l'istruzione atomica bisogna avere minimo compute capability 1.1 (la mia è 1.2), pertanto bisogna aggiungere un parametro al compilatore: "-arch sm_12" che indica di compilare usando compute capability 1.2.
Ho provato in mille modi ad aggiungere quel parametro ma il compilatore mi spara sempre fuori l'errore: " error: identifier "atomicInc" is undefined"
Vi chiedo come si fa ad aggiungere quel parametro al compilatore in VisualStudio 2008? Uso il compilatore nvcc.

Mi sono scaricato l'SDK CUDA e c'è un esempio molto interessante che si chiama "Simple Atomic Intrinsics" il quale dimostra come usare le istruzioni atomiche. Mi sono guardato il codice, riesco a compilarlo e eseguirlo e funziona perfettamente...... ma il bello è che ho guardato di quali include fa uso, ho guardato le proprietà del progetto.......ho usato le stesse include nel mio progetto e ho usato le stesse impostazioni come nell'esempio del SDK CUDA, ma l'esempio funziona, invece a me continua a spararmi l'errore sull'istruzione atomica non capisco perchè

Qualsiasi suggerimento è ben accetto!!
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 30-09-2010, 15:49   #12
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
Quote:
Originariamente inviato da Tommo Guarda i messaggi
La GPU ha la capacità di eseguire algoritmi O(n) in circa O(1)
Lo scopo è creare un algoritmo O(n) dove ogni elemento ha il suo thread...
Caricare (load) la GPU con tutti gli input ha complessita' O(n) (li carichi serialmente)
Se quindi i calcoli sono banali e sono bloccanti, penso che convenga farli fare direttamente alla CPU.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto.
E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 30-09-2010, 16:44   #13
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Grazie per la risposta, ma quello che avevo scritto sopra non c'entra niente con la mia ultima richiesta. Visto che si tratta sempre di istruzioni atomiche non volevo aprire un altro thread.

Comunque devo usare la "atomicInc()" solo in un blocco al termine dell'esecuzione di tutti gli altri blocchi......so benissimo che le istruzioni atomiche rallentano ma devo usarla perforza.......tu sapresti come fare per usare quella dannata atomicInc?

Ultima modifica di HRBF : 30-09-2010 alle 16:48.
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 30-09-2010, 17:08   #14
Torav
Senior Member
 
Iscritto dal: Dec 2005
Messaggi: 558
L'opzione da passare è -arch=sm_xx, dove nel tuo caso xx è 12 (se non ho capito male!) nvcc --help dovrebbe darti tutte le opzioni possibili
Torav è offline   Rispondi citando il messaggio o parte di esso
Old 30-09-2010, 20:03   #15
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Quote:
Originariamente inviato da Torav Guarda i messaggi
L'opzione da passare è -arch=sm_xx, dove nel tuo caso xx è 12 (se non ho capito male!) nvcc --help dovrebbe darti tutte le opzioni possibili
Grazie per la risposta, ho provato ma non compila mi dice: " fatal error C1189: #error : -- incorrect inclusion of a cudart header file c:\cuda\include\crt\func_macro.h "

Ho provato a passare al compilatore "-arch sm_12" oppure "-arch=sm_12" se non mi da l'errore di inclusione dell'header file che ho riportato qui sopra, mi dice sempre "atomicInc() undefined"

La cosa assurda è che ho fatto una copia del progetto dall'SDK CUDA (se lo compilo funziona) quello dove mostra un esempio di utilizzo delle funzioni atomiche, ci ho messo i miei sorgenti, e compilando mi da sempre l'errore sull'atomicInc()

Boh non so più cosa pensare.
HRBF è offline   Rispondi citando il messaggio o parte di esso
Old 01-10-2010, 15:46   #16
Torav
Senior Member
 
Iscritto dal: Dec 2005
Messaggi: 558
Ma per gli include usi path relativi o metti solo #include <cuda_runtime.h> o che so io? Perché in questo caso devi dire al compilatore dove cercare i file header (e io non so come questo si faccia con visual studio).
Torav è offline   Rispondi citando il messaggio o parte di esso
Old 03-10-2010, 15:54   #17
HRBF
Member
 
Iscritto dal: Aug 2010
Messaggi: 88
Quote:
Originariamente inviato da Torav Guarda i messaggi
Ma per gli include usi path relativi o metti solo #include <cuda_runtime.h> o che so io? Perché in questo caso devi dire al compilatore dove cercare i file header (e io non so come questo si faccia con visual studio).
Ciao, per gli include uso la forma classica: #include <cuda_runtime.h> gli ho passato anche i percorsi degli header al compilatore ma niente, sempre errore sulla funzione atomica.
Ci ho rinunciato, ho trovato un altro algoritmo che non fa uso della funzione atomica
HRBF è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi Recensione HUAWEI Mate X7: un foldable ottimo, m...
Nioh 3: souls-like punitivo e Action RPG Nioh 3: souls-like punitivo e Action RPG
Test in super anteprima di Navimow i220 LiDAR: il robot tagliaerba per tutti Test in super anteprima di Navimow i220 LiDAR: i...
Dark Perk Ergo e Sym provati tra wireless, software via browser e peso ridotto Dark Perk Ergo e Sym provati tra wireless, softw...
DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker DJI RS 5: stabilizzazione e tracking intelligent...
Reddit punterà sull'AI per miglio...
Samsung ha obiettivi molto ambiziosi per...
I produttori non faranno sconti sulle me...
Ubisoft potrebbe cedere pezzi se il pian...
Qualcomm potrebbe utilizzare una tecnolo...
Starfield per Nintendo Switch 2 potrebbe...
Un MacBook Pro a -300€, i MacBook Air M4...
Amazon abbassa i prezzi sugli iPhone: sc...
Amazon, ancora sconti sugli smartphone A...
iPhone Air 2 'riciclerà' alcuni c...
Offerta Amazon da non perdere: lo speake...
Nioh 3 debutta alla grande su Steam: pri...
Al centro della Via Lattea ci potrebbe e...
Elon Musk ora guarda alla Luna: SpaceX p...
La Cina ha lanciato nuovamente lo spazio...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 21:53.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v