Intereting Posts
Разделение шестнадцатеричных escape-последовательностей в строках Как передать переменную в mysql_query Почему неинициализированная переменная в C все еще производит выход Разница в использовании между malloc и calloc Написание распределенных массивов с использованием MPI-IO и декартовой топологии оценка математического выражения – очень быстро – с объективным c GCC, C: определение имени предупреждения по умолчанию для использования в #pragma ignore Проблемы с захватом видео и fps OpenCV Как gcc вычисляет необходимое пространство для структуры? разница между & array и & array при передаче функции C Программа Ncurses завершается при изменении размера терминала Совместимость типов указателей функции C Использование _crtBreakAlloc для поиска утечек памяти – идентификатор «_crtBreakAlloc» не определен Точное значение double в десятичной и плавающей? Как использовать функцию wait () при разветвлении нескольких процессов?

Генерация случайного числа в ядре Cuda в различном диапазоне

Я пытаюсь генерировать случайные числа случайных чисел в ядре cuda. Я хочу генерировать случайные числа из равномерного распределения и в целочисленной форме, начиная с 1 до 8. Случайные числа будут разными для каждого из streamов. Диапазон, до которого может генерироваться случайное число, также будет варьироваться от одного streamа к другому. Максимум диапазона в одном streamе может быть как 2, так и в другом streamе, он может быть высоким, как 8, но не выше этого. Итак, я приведу пример ниже того, как я хочу, чтобы числа были сгенерированы:

In thread#1 --> maximum of the range is 2 and so the random number should be between 1 and 2 In thread#2 --> maximum of the range is 6 and so the random number should be between 1 and 6 In thread#3 --> maximum of the range is 5 and so the random number should be between 1 and 5 

и так далее…

Любая помощь будет очень высоко ценится. Спасибо.

EDIT: Я отредактировал свой ответ, чтобы исправить некоторые недостатки, указанные в других ответах (@tudorturcu) и комментарии.

  1. Используйте CURAND для создания равномерного распределения между 0.0 и 1.0
  2. Затем умножьте это на желаемый диапазон (наибольшее значение – наименьшее значение + 0.999999).
  3. Затем добавьте смещение (+ наименьшее значение).
  4. Затем усечь на целое число.

Что-то вроде этого в вашем коде устройства:

 int idx = threadIdx.x+blockDim.x*blockIdx.x; // assume have already set up curand and generated state for each thread... // assume ranges vary by thread index float myrandf = curand_uniform(&(my_curandstate[idx])); myrandf *= (max_rand_int[idx] - min_rand_int[idx] + 0.999999); myrandf += min_rand_int[idx]; int myrand = (int)truncf(myrandf); 

Вам следует:

 #include  

для truncf

Вот полный пример:

 $ cat t527.cu #include  #include  #include  #include  #include  #define MIN 2 #define MAX 7 #define ITER 10000000 __global__ void setup_kernel(curandState *state){ int idx = threadIdx.x+blockDim.x*blockIdx.x; curand_init(1234, idx, 0, &state[idx]); } __global__ void generate_kernel(curandState *my_curandstate, const unsigned int n, const unsigned *max_rand_int, const unsigned *min_rand_int, unsigned int *result){ int idx = threadIdx.x + blockDim.x*blockIdx.x; int count = 0; while (count < n){ float myrandf = curand_uniform(my_curandstate+idx); myrandf *= (max_rand_int[idx] - min_rand_int[idx]+0.999999); myrandf += min_rand_int[idx]; int myrand = (int)truncf(myrandf); assert(myrand <= max_rand_int[idx]); assert(myrand >= min_rand_int[idx]); result[myrand-min_rand_int[idx]]++; count++;} } int main(){ curandState *d_state; cudaMalloc(&d_state, sizeof(curandState)); unsigned *d_result, *h_result; unsigned *d_max_rand_int, *h_max_rand_int, *d_min_rand_int, *h_min_rand_int; cudaMalloc(&d_result, (MAX-MIN+1) * sizeof(unsigned)); h_result = (unsigned *)malloc((MAX-MIN+1)*sizeof(unsigned)); cudaMalloc(&d_max_rand_int, sizeof(unsigned)); h_max_rand_int = (unsigned *)malloc(sizeof(unsigned)); cudaMalloc(&d_min_rand_int, sizeof(unsigned)); h_min_rand_int = (unsigned *)malloc(sizeof(unsigned)); cudaMemset(d_result, 0, (MAX-MIN+1)*sizeof(unsigned)); setup_kernel<<<1,1>>>(d_state); *h_max_rand_int = MAX; *h_min_rand_int = MIN; cudaMemcpy(d_max_rand_int, h_max_rand_int, sizeof(unsigned), cudaMemcpyHostToDevice); cudaMemcpy(d_min_rand_int, h_min_rand_int, sizeof(unsigned), cudaMemcpyHostToDevice); generate_kernel<<<1,1>>>(d_state, ITER, d_max_rand_int, d_min_rand_int, d_result); cudaMemcpy(h_result, d_result, (MAX-MIN+1) * sizeof(unsigned), cudaMemcpyDeviceToHost); printf("Bin: Count: \n"); for (int i = MIN; i <= MAX; i++) printf("%d %d\n", i, h_result[i-MIN]); return 0; } $ nvcc -arch=sm_20 -o t527 t527.cu -lcurand $ cuda-memcheck ./t527 ========= CUDA-MEMCHECK Bin: Count: 2 1665496 3 1668130 4 1667644 5 1667435 6 1665026 7 1666269 ========= ERROR SUMMARY: 0 errors $ 

@ Пример Роберта не генерирует совершенно равномерного распределения (хотя все числа в диапазоне генерируются, и все сгенерированные числа находятся в диапазоне). Как наименьшее, так и наибольшее значение имеют 0,5 вероятность выбора остальных чисел в диапазоне.

На шаге 2 вы должны умножить число значений в диапазоне: (наибольшее значение – наименьшее значение + 0.999999 ). *

На шаге 3 смещение должно быть (+ наименьшее значение) вместо (+ наименьшее значение + 0,5).

Шаги 1 и 4 остаются прежними.

* Как отметил К.Керски, 1.0 включен в дистрибутив. Добавление 1.0 вместо 0.99999 иногда приводило бы к числу за пределами требуемого диапазона.