Генерация случайных чисел из гауссовского распределения в CUDA - PullRequest
2 голосов
/ 20 января 2011

Я много искал в Интернете, чтобы найти способ генерировать случайные числа на моем устройстве CUDA, в ядре.Числа должны быть из гауссовского распределения.

Лучшее, что я нашел , было от самой NVIDIA.Это алгоритм Уоллеса, который использует равномерное распределение для построения гауссовского распределения.Но примеры кода, которые они дают, лишены объяснения, и мне действительно нужно понять, как работает алгоритм, особенно на устройстве.Например, они дают:

 __device__ void generateRandomNumbers_wallace(  
unsigned seed,  // Initialization seed  
 float *chi2Corrections,  // Set of correction values  
 float *globalPool,  // Input random number pool  
 float *output  // Output random numbers  


    unsigned tid=threadIdx.x;  
    // Load global pool into shared memory.  
     unsigned offset = __mul24(POOL_SIZE, blockIdx.x);  
    for( int i = 0; i < 4; i++ )  
      pool[tid+THREADS*i] = globalPool[offset+TOTAL_THREADS*i+tid];  
    __syncthreads();  
      const unsigned lcg_a=241;  
      const unsigned lcg_c=59;  
      const unsigned lcg_m=256;  
      const unsigned mod_mask = lcg_m-1;  
      seed=(seed+tid)&mod_mask ;  
      // Loop generating outputs repeatedly  
     for( int loop = 0; loop < OUTPUTS_PER_RUN; loop++ )  
      {  
        Transform();  
        unsigned intermediate_address;  
        i_a = __mul24(loop,8*TOTAL_THREADS)+8*THREADS *  
          blockIdx.x + threadIdx.x;  
        float chi2CorrAndScale=chi2Corrections[  
          blockIdx.x * OUTPUTS_PER_RUN + loop];  
        for( i = 0; i < 4; i++ )  
          output[i_a + i*THREADS]=chi2CorrAndScale*pool[tid+THREADS*i];  
    }  

Прежде всего, многие из объявленных переменных даже не используются в функции!И я действительно не понимаю, для чего «8» во втором цикле.Я понимаю, что "4" в других циклах как-то связано с блоком ортогональной матрицы 4x4, я прав?Кто-нибудь может дать мне лучшее представление о том, что здесь происходит?Или у кого-нибудь есть другой способ генерации случайных гауссовых чисел в ядре CUDA?Примеры кода будут высоко оценены.

Спасибо!

Ответы [ 3 ]

4 голосов
/ 22 января 2011

Вы можете использовать CURAND , который входит в комплект CUDA Toolkit (версия 3.2 и выше). Это было бы намного проще!

Несколько примечаний по коду, который вы разместили:

  • Генератор Уолласа преобразует гауссовский в гауссовский (то есть, не однородный с гауссовским)
  • В коде CUDA есть две неявные переменные: blockIdx и threadIdx - они определяют индекс блока и индекс потока с помощью блока, см. Руководство по программированию CUDA *1013* для получения дополнительной информации
  • В коде используется __mul24, в sm_20 и более поздних версиях это на самом деле медленнее, чем в "обычном" 32-битном умножении, поэтому я бы его избегал (даже для более старых архитектур для простоты)
1 голос
/ 19 июня 2012

Быстрое преобразование Уолша-Адамара осуществляется с помощью шаблонов сложения и вычитания. Следовательно, применима центральная предельная теорема. Массив равномерных случайных чисел, который подвергается преобразованию Уолша Адамара, будет иметь распределение Гаусса / Нормала Есть некоторые незначительные технические детали об этом. Алгоритм не был обнаружен Уоллесом. Впервые он был опубликован в журнале Servo Magazine примерно в 1993/1994 годах мной. У меня есть код о преобразовании Уолша Адамара на сайте www.code.google.com/p/lemontree С Уважением, Шон О'Коннор

1 голос
/ 20 января 2011

Метод Бокса-Мюллера также хорош.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...