Domanda

Ho lottato per tutto il giorno, sto cercando di ottenere un generatore di numeri casuali per le discussioni nel mio codice CUDA. Ho esaminato tutti i forum e sì, questo argomento si presenta un po ', ma ho passato ore a cercare di svelare tutti i tipi di codice senza alcun risultato. Se qualcuno conosce un metodo semplice, probabilmente un kernel dispositivo che può essere chiamato per restituire un float casuale tra 0 e 1, o un numero intero che posso trasformare, sarei molto grato.

Di nuovo, spero di usare il numero casuale nel kernel, proprio come rand () per esempio.

Grazie in anticipo

È stato utile?

Soluzione

Non sono sicuro di capire perché hai bisogno di qualcosa di speciale. Qualsiasi PRNG tradizionale dovrebbe eseguire il port più o meno direttamente. Un congruential lineare dovrebbe funzionare correttamente. Hai delle proprietà speciali che stai cercando di stabilire?

Altri suggerimenti

Per chiunque sia interessato, ora puoi farlo tramite cuRAND .

Penso che qualsiasi discussione su questa domanda debba rispondere alla richiesta originale di Zenna e che sia per un'implementazione a livello di thread . In particolare una funzione del dispositivo che può essere richiamata da un kernel o thread . Scusami se ho esagerato con " in grassetto " frasi ma penso davvero che le risposte finora non stiano affrontando esattamente ciò che si sta cercando qui.

La libreria cuRAND è la soluzione migliore. Apprezzo il fatto che le persone vogliano reinventare la ruota (fa apprezzare e utilizzare più correttamente le librerie di terze parti), ma i generatori di numeri ad alta qualità e prestazioni elevate sono abbondanti e ben testati. Le migliori informazioni che posso consigliare sono sulla documentazione per la libreria GSL sui diversi generatori qui: http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html

Per qualsiasi codice serio è meglio usare uno dei principali algoritmi che matematici / informatici hanno messo in campo più e più volte alla ricerca di debolezze sistemiche. Il "mersenne twister" è qualcosa con un punto (ciclo ripetuto) nell'ordine di 10 ^ 6000 (l'algoritmo MT19997 significa "Mersenne Twister 2 ^ 19997") che è stato appositamente adattato per Nvidia da usare a livello di thread all'interno di thread dello stesso warp usando thread id chiama come semi. Vedi articolo qui: http: / /developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf . Attualmente sto lavorando per implementare qualcosa usando questa libreria e se riesco a farlo funzionare correttamente pubblicherò il mio codice. Nvidia ha alcuni esempi nel loro sito di documentazione per l'attuale toolkit CUDA.

NOTA: Solo per la cronaca non lavoro per Nvidia, ma ammetterò che la loro documentazione e il design dell'astrazione per CUDA sono qualcosa di cui sono stato finora impressionato.


A seconda della tua applicazione dovresti essere cauto nell'usare i LCG senza considerare se i flussi (un flusso per thread) si sovrapporranno. Potresti implementare un cavalluccio con LCG, ma allora dovresti avere un LCG di periodo sufficientemente lungo per garantire che la sequenza non si ripeta.

Un esempio di leapfrog potrebbe essere:

template <typename ValueType>
__device__ void leapfrog(unsigned long &a, unsigned long &c, int leap)
{
    unsigned long an = a;
    for (int i = 1 ; i < leap ; i++)
        an *= a;
    c = c * ((an - 1) / (a - 1));
    a = an;
}

template <typename ValueType>
__device__ ValueType quickrand(unsigned long &seed, const unsigned long a, const unsigned long c)
{
    seed = seed * a;
    return seed;
}

template <typename ValueType>
__global__ void mykernel(
    unsigned long *d_seeds)
{
    // RNG parameters
    unsigned long a = 1664525L;
    unsigned long c = 1013904223L;
    unsigned long ainit = a;
    unsigned long cinit = c;
    unsigned long seed;

    // Generate local seed
    seed = d_seeds[bid];
    leapfrog<ValueType>(ainit, cinit, tid);
    quickrand<ValueType>(seed, ainit, cinit);
    leapfrog<ValueType>(a, c, blockDim.x);

    ...
}

Ma allora il periodo di quel generatore è probabilmente insufficiente nella maggior parte dei casi.

Ad essere sincero, esaminerei l'utilizzo di una libreria di terze parti come NAG . Ci sono anche alcuni generatori batch nell'SDK, ma probabilmente non è quello che stai cercando in questo caso.

Modifica

Dato che questo è stato appena votato, penso che valga la pena aggiornare per menzionare che cuRAND , as menzionato da risposte più recenti a questa domanda, è disponibile e fornisce un numero di generatori e distribuzioni. Questo è sicuramente il punto di partenza più semplice.

Il modo migliore per farlo è scrivere la tua funzione dispositivo , ecco quella

void RNG()
{   
    unsigned int m_w = 150;
    unsigned int m_z = 40;

    for(int i=0; i < 100; i++)
    {
        m_z = 36969 * (m_z & 65535) + (m_z >> 16);
        m_w = 18000 * (m_w & 65535) + (m_w >> 16);

        cout <<(m_z << 16) + m_w << endl;  /* 32-bit result */
    }
}

Ti darà 100 numeri casuali con risultato a 32 bit.

Se vuoi numeri casuali tra 1 e 1000, puoi anche prendere il risultato% 1000 , sia nel punto di consumo, sia nel punto di generazione:

((m_z << 16) + m_w)%1000

La modifica dei valori iniziali di m_w e m_z (nell'esempio, 150 e 40) consente di ottenere risultati diversi ogni volta. Puoi usare threadIdx.x come uno di questi, il che dovrebbe darti ogni volta diverse serie pseudocasuali.

Volevo aggiungere che funziona 2 volte più velocemente della funzione rand () e funziona alla grande;)

Esiste un pacchetto MDGPU (GPL) che include un'implementazione della funzione GNU rand48 () per CUDA qui .

L'ho trovato (abbastanza facilmente, usando Google, che presumo tu abbia provato :-) sui forum NVidia qui .

Non ho trovato un buon generatore di numeri paralleli per CUDA, tuttavia ho trovato un generatore di numeri casuali parallelo basato sulla ricerca accademica qui: http://sprng.cs.fsu.edu/

Puoi provare Mersenne Twister per GPU

Si basa sul Fast Mersenne Twister (SFMT) orientato al SIMD che è un generatore di numeri casuali abbastanza veloce e affidabile. Supera i test DIEHARD Marsaglia per i generatori di numeri casuali.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top