2016-12-12 21 views
1

Когда мы пишем ядро ​​CUDA, мы всегда делаем это, чтобы гарантировать, что семя может быть обновлено.Как гарантировать, что семена генератора случайных чисел будут различаться каждый раз в тяге

__global__ void kernel(curandState *globalState){ 
     curandState *localState; 
     localState = globalState; 
     // generate random number with localState. 
     globalState = localState; 
} 

и если мы запускаем ядро ​​несколько раз, случайное число всегда может отличаться. Мой вопрос заключается в том, что если мы хотим использовать тягу для генерации случайных чисел, основанных на этот вопрос: Generating a random number vector between 0 and 1.0 using Thrust

и ответ talonmies', когда нам нужно запустить несколько раз с тем же функтором prg, как мы могли бы иметь другое семя для каждой операции? Я пытался переписать код следующим образом:

#include<thrust/random.h> 
#include<thrust/device_vector.h> 
#include<thrust/transform.h> 
#include<thrust/iterator/counting_iterator.h> 
#include<iostream> 
#include<time.h> 

struct prg 
{ 
    float a, b; 
    unsigned int N; 

    __host__ __device__ 
    prg(float _a=0.f, float _b=1.f, unsigned int _N = time(NULL)) : a(_a), b(_b), N(_N) {}; 

    __host__ __device__ 
     float operator()(const unsigned int n) const 
     { 
      thrust::default_random_engine rng(N); 
      thrust::uniform_real_distribution<float> dist(a, b); 
      rng.discard(n); 
      return dist(rng); 
     } 
}; 


int main(void) 
{ 
    const int N = 5; 

    thrust::device_vector<float> numbers(N); 
    thrust::counting_iterator<unsigned int> index_sequence_begin(0); 
    // first operation 
    thrust::transform(index_sequence_begin,index_sequence_begin + N, numbers.begin(),prg(1.f,2.f)); 

    for(int i = 0; i < N; i++) 
    { 
     std::cout << numbers[i] << std::endl; 
    } 
    // second operation 
    thrust::transform(index_sequence_begin,index_sequence_begin + N, numbers.begin(),prg(1.f,2.f)); 

    for(int i = 0; i < N; i++) 
    { 
     std::cout << numbers[i] << std::endl; 
    } 

    return 0; 
} 

Первая операция и вторая операция генерации и тот же номер. Я знаю, что это потому, что разница во времени коротка, тогда как мне изменить код, чтобы получить разные случайные числа для этих двух операций? Я предполагаю, что можно назначить семя на основе времени операции (1,2, ..... 10000, 10001, ... N), но будет ли это дорого стоить?

ответ

4

Перефразируя Джона фон Неймана «Ничто так важно, как случайные числа, должно быть оставлено на волю случая».

Если вы не можете гарантировать, что семена для случайных генераторов различны (и, похоже, вы не можете в этом случае), то не пытайтесь использовать разные семена. Используйте один экземпляр генератора семян и возьмите из него разные последовательности.

+0

Спасибо, @talonmies. Будет ли это дорого стоить? например, каждый цикл, i, возьмем rng (i). –

+0

Не должно быть разницы. Все, что вы делаете, передавая другое смещение на вызов преобразования – talonmies

+0

Еще раз спасибо. Я протестировал его и нашел, что время ellapsed почти такое же. –