Pregunta

He luchado con esto todo el día, estoy tratando de obtener un generador de números aleatorios para hilos en mi código CUDA. He revisado todos los foros y sí, este tema aparece bastante, pero he pasado horas tratando de desentrañar todo tipo de códigos en vano. Si alguien conoce un método simple, probablemente un núcleo dispositivo al que se pueda llamar devuelva un flotante aleatorio entre 0 y 1, o un entero que pueda transformar estaría muy agradecido.

Nuevamente, espero usar el número aleatorio en el núcleo, al igual que rand () por ejemplo.

Gracias de antemano

¿Fue útil?

Solución

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

Otros consejos

Para cualquier persona interesada, ahora puede hacerlo a través de cuRAND .

Creo que cualquier discusión sobre esta pregunta debe responder a la solicitud original de Zenna y es para una implementación de nivel de subproceso . Específicamente, una función de dispositivo que se puede invocar desde un núcleo o subproceso . Lo siento si excedí el " en negrita " frases, pero realmente creo que las respuestas hasta ahora no abordan exactamente lo que se busca aquí.

La biblioteca cuRAND es su mejor apuesta. Aprecio que la gente quiera reinventar la rueda (hace que uno aprecie y use más adecuadamente 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 está en 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 usar uno de los algoritmos principales que los matemáticos / informáticos tienen en el suelo una y otra vez en busca de debilidades sistémicas. El " mersenne twister " es algo con un punto (ciclo de repetición) del orden de 10 ^ 6000 (el algoritmo MT19997 significa "Mersenne Twister 2 ^ 19997") que ha sido especialmente adaptado para que Nvidia lo use a nivel de hilo dentro de hilos de la misma urdimbre usando hilo id llama como semillas. Consulte el documento aquí: http: / /developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf . De hecho, estoy trabajando para implementar algo con 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 con lo que hasta ahora me he impresionado.


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

Un ejemplo de salto podría ser:

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 ese generador es probablemente insuficiente en la mayoría de los casos.

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

EDIT

Dado que esto acaba de ser votado, creo que vale la pena actualizarlo para mencionar que cuRAND , como mencionado por respuestas más recientes a esta pregunta, está disponible y proporciona una serie de generadores y distribuciones. Ese es definitivamente el lugar más fácil para comenzar.

La mejor manera para esto es escribir su propia función de dispositivo , aquí está la

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

Te dará 100 números aleatorios con un resultado de 32 bits.

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

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

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

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

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

Lo encontré (con bastante facilidad, usando Google, que supongo que probaste :-) en los foros de NVidia aquí .

No he encontrado un buen generador de números paralelos para CUDA, sin embargo, encontré un generador de números aleatorios paralelos basado en investigaciones académicas aquí: http://sprng.cs.fsu.edu/

Puede probar Mersenne Twister para GPU

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top