在cuda内核中生成随机数
我正在写一个cuda程序,我需要生成一个随机变量,这个随机变量将由正态分布生成。我希望随机变量的值限制在0到8之间。因此,我希望在核函数中生成随机变量,然后随机变量的结果将用于进一步的使用。我正计划利用库兰图书馆来达到这个目的。我一直在尝试使用curand_普通设备api生成值,但没有成功。如果有人能给我提供内核函数代码,那将非常有帮助。谢谢你的帮助 下面提供的代码是我在gpu中搜索的cpu实现:在cuda内核中生成随机数,cuda,gpgpu,normal-distribution,Cuda,Gpgpu,Normal Distribution,我正在写一个cuda程序,我需要生成一个随机变量,这个随机变量将由正态分布生成。我希望随机变量的值限制在0到8之间。因此,我希望在核函数中生成随机变量,然后随机变量的结果将用于进一步的使用。我正计划利用库兰图书馆来达到这个目的。我一直在尝试使用curand_普通设备api生成值,但没有成功。如果有人能给我提供内核函数代码,那将非常有帮助。谢谢你的帮助 下面提供的代码是我在gpu中搜索的cpu实现: #include "stdafx.h" #include <iostream&g
#include "stdafx.h"
#include <iostream>
#include <random>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
const int nrolls=10000; // number of experiments
const int nstars=100; // maximum number of stars to distribute
int i;
default_random_engine generator;
normal_distribution<double> distribution(0.0,3);
for (i=0;i<=nstars;i++)
{ int number = distribution(generator);
printf("%d\n\n",number);
}
return 0;
}
#包括“stdafx.h”
#包括
#包括
使用名称空间std;
int _tmain(int argc,_TCHAR*argv[]
{
const int nrolls=10000;//实验次数
const int nstars=100;//要分配的最大恒星数
int i;
默认的随机引擎生成器;
正态分布(0.0,3);
对于(i=0;i这里有一个调整,它将产生一组近似“正态”分布的随机数,这些随机数的离散值大约在0到8之间。我不理解评论中要求的范围为0到8,平均值为0
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <curand_kernel.h>
#include <math.h>
#define SCALE 2.0
#define SHIFT 4.5
#define DISCRETE
#define BLOCKS 1024
#define THREADS 512
#define CUDA_CALL(x) do { if((x) != cudaSuccess) { \
printf("Error at %s:%d\n",__FILE__,__LINE__); \
return EXIT_FAILURE;}} while(0)
__global__ void setup_kernel(curandState *state)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
/* Each thread gets different seed, a different sequence
number, no offset */
curand_init(7+id, id, 0, &state[id]);
}
__global__ void generate_normal_kernel(curandState *state,
int *result)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
float x;
/* Copy state to local memory for efficiency */
curandState localState = state[id];
/* Generate pseudo-random uniforms */
for(int n = 0; n < 10; n++) {
x = (curand_normal(&localState) * SCALE)+SHIFT;
/* Discretize */
#if defined DISCRETE
x = truncf(x);
#endif
}
/* Copy state back to global memory */
state[id] = localState;
/* Store last generated result per thread */
result[id] = (int) x;
}
int main(int argc, char *argv[])
{
int i;
unsigned int total;
curandState *devStates;
int *devResults, *hostResults;
int device;
struct cudaDeviceProp properties;
CUDA_CALL(cudaGetDevice(&device));
CUDA_CALL(cudaGetDeviceProperties(&properties,device));
/* Allocate space for results on host */
hostResults = (int *)calloc(THREADS * BLOCKS, sizeof(int));
/* Allocate space for results on device */
CUDA_CALL(cudaMalloc((void **)&devResults, BLOCKS * THREADS *
sizeof(int)));
/* Set results to 0 */
CUDA_CALL(cudaMemset(devResults, 0, THREADS * BLOCKS *
sizeof(int)));
/* Allocate space for prng states on device */
CUDA_CALL(cudaMalloc((void **)&devStates, THREADS * BLOCKS *
sizeof(curandState)));
/* Setup prng states */
setup_kernel<<<BLOCKS, THREADS>>>(devStates);
/* Generate and use uniform pseudo-random */
generate_normal_kernel<<<BLOCKS, THREADS>>>(devStates, devResults);
/* Copy device memory to host */
CUDA_CALL(cudaMemcpy(hostResults, devResults, BLOCKS * THREADS *
sizeof(int), cudaMemcpyDeviceToHost));
/* Show result */
if (THREADS*BLOCKS > 20){
printf("First 20 stored results:\n");
for (i=0; i<20; i++)
printf("%d\n", hostResults[i]);
}
total = 0;
for(i = 0; i < BLOCKS * THREADS; i++) {
total += hostResults[i];
}
printf("Results mean = %f\n", (total/(1.0*BLOCKS*THREADS)));
/* Cleanup */
CUDA_CALL(cudaFree(devStates));
CUDA_CALL(cudaFree(devResults));
free(hostResults);
return EXIT_SUCCESS;
}
假设您有一个cc2.0或更高的GPU
如果没有,则可以使用以下工具进行编译:
nvcc -o uniform uniform.cu
在本例中,编译器警告double将降级为float,可以忽略该警告
线程
和块
是机器限制范围内的任意选择。您可以修改它们以适应您自己代码的特定启动配置。这里有一个调整,它将产生近似“正常”的-分布的一组随机数,其离散值大约在0到8之间。我不理解评论中要求的0到8的范围,平均值为0
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <curand_kernel.h>
#include <math.h>
#define SCALE 2.0
#define SHIFT 4.5
#define DISCRETE
#define BLOCKS 1024
#define THREADS 512
#define CUDA_CALL(x) do { if((x) != cudaSuccess) { \
printf("Error at %s:%d\n",__FILE__,__LINE__); \
return EXIT_FAILURE;}} while(0)
__global__ void setup_kernel(curandState *state)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
/* Each thread gets different seed, a different sequence
number, no offset */
curand_init(7+id, id, 0, &state[id]);
}
__global__ void generate_normal_kernel(curandState *state,
int *result)
{
int id = threadIdx.x + blockIdx.x * blockDim.x;
float x;
/* Copy state to local memory for efficiency */
curandState localState = state[id];
/* Generate pseudo-random uniforms */
for(int n = 0; n < 10; n++) {
x = (curand_normal(&localState) * SCALE)+SHIFT;
/* Discretize */
#if defined DISCRETE
x = truncf(x);
#endif
}
/* Copy state back to global memory */
state[id] = localState;
/* Store last generated result per thread */
result[id] = (int) x;
}
int main(int argc, char *argv[])
{
int i;
unsigned int total;
curandState *devStates;
int *devResults, *hostResults;
int device;
struct cudaDeviceProp properties;
CUDA_CALL(cudaGetDevice(&device));
CUDA_CALL(cudaGetDeviceProperties(&properties,device));
/* Allocate space for results on host */
hostResults = (int *)calloc(THREADS * BLOCKS, sizeof(int));
/* Allocate space for results on device */
CUDA_CALL(cudaMalloc((void **)&devResults, BLOCKS * THREADS *
sizeof(int)));
/* Set results to 0 */
CUDA_CALL(cudaMemset(devResults, 0, THREADS * BLOCKS *
sizeof(int)));
/* Allocate space for prng states on device */
CUDA_CALL(cudaMalloc((void **)&devStates, THREADS * BLOCKS *
sizeof(curandState)));
/* Setup prng states */
setup_kernel<<<BLOCKS, THREADS>>>(devStates);
/* Generate and use uniform pseudo-random */
generate_normal_kernel<<<BLOCKS, THREADS>>>(devStates, devResults);
/* Copy device memory to host */
CUDA_CALL(cudaMemcpy(hostResults, devResults, BLOCKS * THREADS *
sizeof(int), cudaMemcpyDeviceToHost));
/* Show result */
if (THREADS*BLOCKS > 20){
printf("First 20 stored results:\n");
for (i=0; i<20; i++)
printf("%d\n", hostResults[i]);
}
total = 0;
for(i = 0; i < BLOCKS * THREADS; i++) {
total += hostResults[i];
}
printf("Results mean = %f\n", (total/(1.0*BLOCKS*THREADS)));
/* Cleanup */
CUDA_CALL(cudaFree(devStates));
CUDA_CALL(cudaFree(devResults));
free(hostResults);
return EXIT_SUCCESS;
}
假设您有一个cc2.0或更高的GPU
如果没有,则可以使用以下工具进行编译:
nvcc -o uniform uniform.cu
在本例中,编译器警告double将降级为float,可以忽略该警告
线程
和块
是机器限制范围内的任意选择。您可以修改它们以适合您自己代码的特定启动配置。为什么不发布您尝试过但未成功的方法?这通常是个好主意。“为我编写代码”类型问题不太可能得到很好的结果。您看过设备API示例吗?它提供了一个完整的程序,其中一个generate\u uniform\u kernel
选项应该与您的要求非常接近。嗨!嗨!谢谢您的支持。实际上,我已经看过设备API示例并复制了一些内容我不知道如何得到一个在0到8范围内服从正态分布的随机变量。还有一件事是,我尝试了中提到的程序,并在中将curand_uniform改为curand_normal顶部设备函数,我得到了一些结果。您想要一个离散均匀分布,它接受值(0,1,2,3,4,5,6,7,8)(即整数)还是一个连续值均匀分布,它接受值介于0.0和8.0之间(即浮点数)我想要从0到8的离散数,平均值为0。我不知道如何用精确的统计数据创建一个正态分布,占据一个有限的范围。你知道怎么做吗?你怎么处理分布的尾部?我猜平均值为零,你的意思是你只想要正态分布的正半部分,集中在零?显然不是如果范围从零扩展到正值,则结果分布的平均值不能为零。我不清楚这是一个CUDA问题。您有代表性的非CUDA(基于CPU的)吗实现您要做的事情?为什么不发布您尝试过但未成功的方法?这通常是个好主意。“为我编写代码”类型问题不太可能得到很好的结果。您看过设备API示例吗?它提供了一个完整的程序,其中一个generate\u uniform\u kernel
选项应该与您的要求非常接近。嗨!嗨!谢谢您的支持。实际上,我已经看过设备API示例并复制了一些内容我不知道如何得到一个在0到8范围内服从正态分布的随机变量。还有一件事是,我尝试了中提到的程序,并在中将curand_uniform改为curand_normal顶部设备函数,我得到了一些结果。您想要一个离散均匀分布,它接受值(0,1,2,3,4,5,6,7,8)(即整数)还是一个连续值均匀分布,它接受值介于0.0和8.0之间(即浮点数)我想要从0到8的离散数,平均值为0。我不知道如何用精确的统计数据创建一个正态分布,占据一个有限的范围。你知道怎么做吗?你怎么处理分布的尾部?我猜平均值为零,你的意思是你只想要正态分布的正半部分,集中在零?显然不是如果范围从零扩展到正值,则结果分布的平均值不能为零。我不清楚这是一个CUDA问题。您是否有一个代表性的非CUDA(基于CPU的)实现来实现您正在尝试的操作?