2009-05-08 64 views
14

He luchado con esto todo el día, estoy tratando de obtener un generador de números aleatorios para los hilos en mi código CUDA. He revisado todos los foros y sí, este tema me parece bastante interesante, pero he pasado horas intentando descifrar todo tipo de códigos sin resultado. Si alguien sabe de un método simple, probablemente un kernel del dispositivo al que se puede llamar para devolver un flotante aleatorio entre 0 y 1, o un número entero que pueda transformar, le estaría muy agradecido.Generador de números aleatorios en CUDA

De nuevo, espero usar el número aleatorio en el kernel, al igual que rand(), por ejemplo.

Gracias de antemano

+0

Alguna información útil: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch37.html – Jesper

Respuesta

5

no estoy seguro de entender por qué necesita nada especial. Cualquier PRNG tradicional debe portar más o menos directamente. Un linear congruential debería funcionar bien. ¿Tiene algunas propiedades especiales que está tratando de establecer?

+0

Creo que está buscando una biblioteca a la que pueda llamar, no para implementarla él mismo. Sigue siendo una buena respuesta para indicarle una solución. – lothar

+0

lineal congruente es muy simple de implementar. Puedes hacer esto con CUDA teniendo un PRNG separado con su propio estado en cada hilo. –

+0

Eso es lo que me confundió un poco. Cada hilo diría que fue sembrado de su id del hilo, pero ¿no comenzarían a superponerse lo suficientemente pronto? – zenna

2

Hay un paquete MDGPU (GPL) que incluye una implementación de la función GNU rand48() para CUDA here.

Lo encontré (bastante fácil, usando Google, que supongo que probaste :-) en los foros de NVidia here.

+0

Sí encontré que también .. pero tuvo problemas para conseguir que se haga lo que yo quiero .. Creo que sólo estoy teniendo un día estúpida .. Voy a comprobar hacia fuera otra vez, gracias – zenna

+0

De acuerdo con los comentarios en el NVidia foro (incluido el del autor) la implementación no funciona bien. –

2

no he encontrado un buen generador de números paralelo para CUDA, Yo sin embargo encontrar un generador de números aleatorios en paralelo basado en la investigación académica aquí: http://sprng.cs.fsu.edu/

+0

¿Alguien sabe de una versión CUDA de este algoritmo? –

+0

¿Qué quiere decir con "bueno"? Dependiendo de sus requisitos, un simple hash MD5 (ver cuDPP) puede ser suficiente. En algunos casos, múltiples Mersenne Twisters pueden ser los mejores ya que tienen un período realmente largo y una buena independencia entre transmisiones. NAG tiene MRG32k3a de l'Ecuyer que funciona muy bien si necesita una única transmisión a través de múltiples hilos/bloques. – Tom

+0

Un buen comienzo sería un generador de números pseudo-aleatorio repetitivo con una baja dependencia entre las células - adecuados, para la creación de un conjunto de matriz de números aleatorios, llenando el contenido de cada matriz con múltiples hilos, pero la creación de las matrices, una tras otra. –

4

En función de la aplicación que se debe tener cuidado con el uso de GLCs sin tener en cuenta si las secuencias (una secuencia por hilo) se superpondrán. Podría implementar un salto con LCG, pero luego necesitaría tener un LCG de período suficientemente largo para garantizar que la secuencia no se repita.

Un ejemplo podría ser LeapFrog:

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); 

    ... 
} 

Pero entonces el período de que el generador es probablemente insuficiente en la mayoría de los casos.

Para ser honesto, me gustaría utilizar una biblioteca de terceros como NAG. También hay algunos generadores de lotes en el SDK, pero probablemente eso no sea lo que está buscando en este caso.

EDITAR

Dado que esto sólo se levantó-votó, supongo que vale la pena actualizar mencionar que cuRAND, como se ha mencionado por respuestas más recientes a esta pregunta, que está disponible y proporciona una serie de generadores y distribuciones. Ese es definitivamente el lugar más fácil para comenzar.

4

La mejor manera para que este está escribiendo su propio función del dispositivo, aquí es el que

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 */ 
    } 
} 

él se puede dar el 100 números aleatorios con resultado de 32 bits.

Si desea algunos números aleatorios entre 1 y 1000, también se puede tomar el result%1000, ya sea en el punto de consumo, o en el punto de generación:

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

Cambiar los valores m_w y m_z de partida (en el ejemplo, 150 y 40) le permite obtener resultados diferentes cada vez. Puede usar threadIdx.x como uno de ellos, lo que le dará diferentes series pseudoaleatorias cada vez.

que quería añadir que funciona 2 veces más rápido que la función rand(), y funciona muy bien;)

+3

Comentario del Editor: Es un poco RNG ordenada, pero en ninguna parte cerca utilizable para el cálculo donde se requieren buenos números aleatorios. Tiene un período de 2^16, no puede abarcar todo el espacio numérico de 32 bits, y es bastante fácilmente reversible debido a un paso simple y un período pequeño. – qdot

4

Creo que cualquier discusión de esta cuestión tiene que responder a la solicitud original de Zenna y que es de un nivel hilo implementación. Específicamente, una función de dispositivo que se puede llamar desde un núcleo o una cadena. Lo siento si exagere las frases "en negrita", pero realmente creo que las respuestas hasta ahora no están abordando lo que se busca aquí.

La biblioteca de cuRAND es su mejor apuesta. Aprecio que la gente quiera reinventar la rueda (hace que uno aprecie y use de forma más adecuada las bibliotecas de terceros), pero los generadores de números de alta calidad y alto rendimiento son abundantes y están bien probados. La mejor información que puedo recomendar es la documentación de la biblioteca GSL en los diferentes generadores aquí: http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html

Para cualquier código serio, es mejor utilizar uno de los algoritmos principales que los matemáticos/informáticos tienen en el terreno y buscando debilidades sistémicas. El "twister de mersenne" es algo con un punto (loop de repetición) del orden de 10^6000 (algoritmo MT19997 significa "Mersenne Twister 2^19997") que ha sido especialmente adaptado para que Nvidia lo utilice a nivel de subproceso dentro de los hilos del mismo warp usando thread id calls como semillas. Ver papel aquí: http://developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf. De hecho, estoy trabajando para implementar algo usando esta biblioteca y si logro que funcione correctamente, publicaré mi código. Nvidia tiene algunos ejemplos en su sitio de documentación para el kit de herramientas actual de CUDA.

NOTA: Solo para el registro, no trabajo para Nvidia, pero admitiré que su documentación y diseño de abstracción para CUDA es algo que hasta ahora me ha impresionado.


0

Se podría probar Mersenne Twister for GPUs

Se basa en orientado a SIMD rápido Mersenne Twister (SFMT) que es un generador de números aleatorios bastante rápido y fiable. Pasa las pruebas Marsaglias DIEHARD para generadores de números aleatorios.

+0

cuRAND ya [proporciona Twister mersenne] (http://docs.nvidia.com/cuda/curand/acknowledgements.html#acknowledgements) implementado para la GPU. –

Cuestiones relacionadas