2012-06-23 17 views
5

Cuda è fantastico e lo sto usando come un matto ma non sto sfruttando tutto il suo potenziale perché sto avendo un problema nel trasferire memoria e mi chiedevo se c'era un modo migliore per ottenere una quantità variabile di memoria fuori. Fondamentalmente invio 65535 item array in Cuda e Cuda analizza ogni elemento di dati in circa 20.000 modi diversi e, se c'è una corrispondenza nella logica dei miei programmi, salva un elenco di 30 int di conseguenza. Pensa alla mia logica di analizzare ogni combinazione diversa e poi a guardare il totale e se il totale è uguale a un numero che sto cercando, allora salva i risultati (che è una lista di 30 int per ogni articolo analizzato).Trasferimento di una grande quantità di memoria variabile da Cuda

Il problema è 65535 (blocchi/voci nell'array di dati) * 20000 (combinazioni totali testate per articolo) = 1.310.700.000. Ciò significa che ho bisogno di creare una matrice di quelle dimensioni per far fronte alla possibilità che tutti i dati siano una corrispondenza positiva (che è estremamente improbabile e la creazione di int output[1310700000][30] sembra folle per la memoria). Sono stato costretto a renderlo più piccolo e inviare meno blocchi da elaborare perché non so come se Cuda può scrivere in modo efficiente in una lista collegata o in una lista di dimensioni dinamiche (con questo approccio scrive l'output sulla memoria host usando il blocco * number_of_different_way_tests).

C'è un modo migliore per farlo? Cuda può in qualche modo scrivere in memoria libera che non deriva dal blocco? Quando provo questo processo sulla CPU, meno del 10% dell'array di oggetti ha una corrispondenza positiva, quindi è estremamente improbabile che utilizzerò tanta memoria ogni volta che invierò il lavoro al kernel.

p.s. Sto guardando sopra e sebbene sia esattamente quello che sto facendo, se la sua confusione è un altro modo di pensarci (non esattamente quello che sto facendo, ma abbastanza buono per capire il problema) sto inviando 20.000 array (che ciascuno contiene 65.535 voci) e aggiungendo ogni oggetto con il suo pari negli altri array e se il totale è uguale a un numero (diciamo 200-210), allora voglio conoscere i numeri aggiunti per ottenere quel risultato corrispondente. Se i numeri sono molto ampi, allora non tutti combaceranno, ma usando il mio approccio sono costretto a malloc quell'enorme quantità di memoria. Posso acquisire i risultati con il mallocing di memoria in meno? Il mio attuale approccio è malloc tanto quanto ho libero, ma sono costretto a eseguire meno blocchi che non sono efficienti (voglio eseguire quanti più blocchi e thread una volta perché mi piace il modo in cui Cuda organizza e gestisce i blocchi) . C'è qualche trucco di Cuda o C che posso usare per questo o sono bloccato con il malloppo dei massimi risultati possibili (e l'acquisto di molta più memoria)?

+0

Che ne dici di alcune righe di codice? – wallyk

+0

Se le corrispondenze positive sono poche, la procedura alternativa che descrivo in [questa risposta] (http://stackoverflow.com/q/11148860/442006) potrebbe essere una buona idea. Aumenteresti l'indice di 30 ogni volta. –

+0

hey @wallyk C'è qualcosa di poco chiaro che posso spiegare di più? o se ritieni che il codice sia necessario, allora posso lavorare sulla creazione di un campione sperato (dato che la mia base di codice attuale è piuttosto grande e dipende da altri file, ho ritenuto che sarebbe stato più confuso e utile). – Lostsoul

risposta

0

Come da grande Roger Dahl answer: La funzionalità che stai cercando si chiama compattazione del flusso.

Probabilmente è necessario fornire un array che contenga spazio per 4 soluzioni per thread perché è probabile che il tentativo di memorizzare direttamente i risultati in una forma compatta crei così tante dipendenze tra i thread che le prestazioni hanno ottenuto nella possibilità di copiare meno dati ritornano all'host vengono persi da un tempo di esecuzione del kernel più lungo. L'eccezione a questo è se quasi tutti i thread non trovano soluzioni. In tal caso, potresti essere in grado di utilizzare un'operazione atomica per mantenere un indice in un array. Quindi, per ciascuna soluzione trovata, la si memorizzerebbe in una matrice in un indice e quindi si utilizzerà un'operazione atomica per aumentare l'indice. Penso che sarebbe sicuro usare atomicAdd() per questo. Prima di memorizzare un risultato, il thread usava atomicAdd() per aumentare l'indice di uno. atomicAdd() restituisce il vecchio valore e il thread può memorizzare il risultato usando il vecchio valore come indice.

Tuttavia, data una situazione più comune, dove c'è un buon numero di risultati, la soluzione migliore sarà eseguire un'operazione di compattazione come passaggio separato. Un modo per farlo è con thrust :: copy_if. Vedi questa domanda per qualche altro background.

Problemi correlati