也许有人还记得咱曾经做过Mente Carlo法球圆周率的程序,当时那个是用的C++写的;现在为了练习CUDA,咱也用CUDA写了一个——8过现在这个程序运行倒是运行了,但是有一个奇怪的问题是:完全一模一样的程序,直接在Terminal里面用./打开得到的误差远高于直接双击图标打开运行得到的误差orz原因不明
如上图所示,同样是512×106个随机点,左边是直接在Terminal里面用./打开得到的结果,得到的圆周率对比实际的圆周率的误差高达7825×10-6,而右边是直接双击打开得到的结果,误差只有24×10-6,而且这不是偶然,无论测试多少次./得到的结果都是高达4位数,而直接打开则一般都是两位数,或者运气好的时候也有一位数的时候orz可以肯定./打开的时候绝对有什么奇怪的效果,但是目前为止查了各种资料未果orz虽然大致可以推测应该是CUDA的随机数函数curand的问题ww CUDA到底是怎么回事www
啊当然,对于Monte Carlo法来说,GPU的运算要远快于CPU,同样是512×106个随机点,咱女仆本上的9400m只要不到两秒钟,而Core 2 Duo(2.26GHz)则要将近一分钟www
嘛,这里把CUDA的代码贴上来,欢迎有兴趣的童鞋研究www
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <curand.h> #include <curand_kernel.h> #define MAX_THREAD 256 #define MAX_COUNT 2000000 /* 最大线程MAX_THREAD 256 每个线程生成随机点个数MAX_COUNT 2000000 */ /* GPU端圆周率函数piGenerator宣言 */ __global__ void piGenerator (float *res, int *count, int *time); /* 主程序 */ int main (int argc, const char * argv[]){ /* CPU端圆周率h_pi、GPU端圆周率d_pi、最终圆周率(平均值)pi、偏差err */ float *h_pi, *d_pi, pi, err; /* 最大线程数maxThread,随机点个数h_count/d_count,随机数初期值设定用时间h_time/d_time,for循环次数i */ int maxThread = MAX_THREAD, *h_count, *d_count, *h_time, *d_time, i; /* CPU端h_pi、h_count、h_time内存确保 */ h_pi = (float *)malloc(sizeof(float) * maxThread); h_count = (int *)malloc(sizeof(int) * 1); h_time = (int *)malloc(sizeof(int) * 1); /* GPU端d_pi、d_count、d_time内存确保 */ cudaMalloc((void **)&d_pi, sizeof(float) * maxThread); cudaMalloc((void **)&d_count, sizeof(int) * 1); cudaMalloc((void **)&d_time, sizeof(int) * 1); /* CPU端随机点个数值h_count及时间值h_time带入 */ h_count[0] = MAX_COUNT; h_time[0] = (int)time(NULL); /* 将h_count及h_time的值带入GPU端d_count及d_time */ cudaMemcpy(d_count, h_count, sizeof(int) * 1, cudaMemcpyHostToDevice); cudaMemcpy(d_time, h_time, sizeof(int) * 1, cudaMemcpyHostToDevice); /* 运行时间测试 */ clock_t start, end; /* 运行时间测试开始 */ start = clock(); /* GPU端函数piGenerator开始运行,1个block,maxThread = 512个thread */ piGenerator<<<1, maxThread>>> (d_pi, d_count, d_time); /* 将GPU生成的圆周率d_pi带入CPU端c_pi */ cudaMemcpy(h_pi, d_pi, sizeof(float) * maxThread, cudaMemcpyDeviceToHost); /* 512个线程生成的圆周率求平均值 */ for (i = 0; i < maxThread; i++) { pi += h_pi[i]; } pi = pi / maxThread; /* 运行时间测试停止 */ end = clock(); /* 求圆周率误差 */ err = pi - (float)M_PI; if (err < 0) { err = -err; } /* 结果输出 */ printf("Points: %d, Generated π: %f, Error: %.0fe-6\n", h_count[0] * maxThread, pi, err * 1000000); printf("Timer: %f sec\n", (float)(end - start)/CLOCKS_PER_SEC); /* CPU端内存释放 */ free(h_pi); free(h_count); free(h_time); /* GPU端内存释放 */ cudaFree(d_pi); cudaFree(d_count); cudaFree(d_time); /* 结束 */ return 0; } __global__ void piGenerator (float *res, int *count, int *time) { /* 1/4圆内点个数a初期值=0,线程ID index_x=threadIdx.x,随机点个数n带入,时间值t带入,for循环次数i */ int a=0, index_x = threadIdx.x, n = *count, t = *time, i; /* 随机点x、y宣言 */ float x, y; /* 圆周率内存保存地址确认 */ res += index_x; /* curand随机函数初期化 */ curandState s; curand_init(t, index_x, 0, &s); /* for循环次数=随机点生成个数 */ for (i = 1; i <= n; i++) { /* 随机点x坐标、y坐标(0<x<1,0<y<1)的随机生成 */ x = curand_uniform(&s); y = curand_uniform(&s); /* 如果随机点在1/4圆圈以内,1/4圆内点个数a+1 */ if (pow(x, 2) + pow(y, 2) <= 1) { a++; } /* 圆周率计算(1/4圆内点个数 / 随机点总数 * 4) */ *res = 4 * (float)a / (float)n; /* 线程同步 */ __syncthreads(); } }
嘛CUDA的事就说到这儿w话说最近宇都宫的大型电器店Yodobashi Camera的店内Layout稍微改了一下,然后似乎成为了BOSE的授权零售商,于是音响区增加了一个BOSE专区!好想要Companion 20啊><好想要Companion 5啊><
话说前几天购物回家的时候在等红灯的时候看到旁边的停车场里面的车——人生\(^o^)/オワタ!!
为了迎接ゆるゆり♪♪而专程购入的ラムレーズン!ラムレーズンうめぇ!!
以上XD
p.s. 虽然很多人都称偶为大大——8过咱真心不觉得咱是大大,至少咱现在还远远达不到咱心里“大大”的标准——虽然咱正在努力成为“大大”www 8过至少现在来说咱真的不是大大!!!!!wwwww
cuda很不错呢,下个学期打算修cuda的课
同样感觉是随机函数生成伪随机时种子的问题
include后面的库呢?
壕夶您好~
话说代码如果不用code圈起来的话就会缺失内容的说
大大!
双击图标比./直接运行多了层处理吧,从来没跟GPU打过交道,更别说CUDA编译器了。。。膜拜大大
同膜拜….
话说 那是神马动漫杂志?
试过这个吗?亲
http://www.pgroup.com/lit/articles/insider/v1n1a1.htm
写的时候省很多事。
你如果来做动漫多好啊,别搞代码了
第一次看到CUDA的代码。。。。
不行不行。。。。看到千反田捕获奉太郎,ヾ(≧▽≦*)o。笑死了=w=
窗口都把壁纸挡住啦!QvQ
代碼什麼的人家完全不懂
昨天各種壞掉,直到今天晚上才恢復
原来是利用CUDA编程QAQ 只会用MC压视频的亚历山大
咱最近是除了Objective-C外,几乎就没有看其他编程语言了…
大学毕业前夕也是各种荒废的时候啊,没有看书的动力…
在这次七月新番当中,摇曳百合、TARI TARI最期待了…
话说车左边的标牌上的字是什么意思啊?
ps:用Siri的Dictation输入真的是好方便啊…
@conanshang
妇产科的标牌啊
@itorr
压视频神马的好怀念 最近都好懒了懒得压视频了
@linfcstmr’助手廚
怎么了
@Bee君
千反田恵瑠最美了
@Leyeang
咱不就正在动漫的液界里面么
@zym9
似乎很方便!8过是收费的orz嘛反正是毕业研究用的
@天羽
Newtype的姊妹志娘type
@maplebeats
嘛肯定有什么不一样的8过咱实在无法想象是啥不一样
@陈少举
咱不是大大
@bi119aTe5hXk
写的时候当然圈了问题是WP还是照样不显示
@萌名雪
现在可以显示了
@keekun
那个已经用时间和thread id初期化了
@星野恵瑠
哎!!!
原来是这样
最后几句好绕口,大大大大= =
最后一段
@掌柜的马甲
掌柜抱抱
555来晚了
最近WEIBO上面也是各种千反田的段子和本子….
@L
薄薄的本子咱也要努力成为大大~
@Phoenix
刚把咧
好复杂的代码……
你好 我想问您一下 我用了您代码中的一部分关于产生随机数的部分 为什么我运行后是一个负值 而且其绝对值很大 另外每一个线程所产生的随机数都相同??
@孤独流浪者
请问具体是哪一部分以及怎么代入的呢?如果可以的话请给我看一下源代码
@星野恵瑠
#include
#include
#include
#include
#include
#include
#include
#include
#define M 43
#define N 20
const int source[M]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
__global__ void kernel(float *a,int *time)
{
__shared__ float cache[N];
int index=threadIdx.x;
int i,t=*time;
curandState s;
curand_init(t, index, 0, &s);
i = curand_uniform(&s);
cache[index]=i;
__syncthreads();
if(index==1)
{
for(int j=0;j<N;j++)
a[j]=cache[j];
}
}
int main()
{
float *a,*dev_a;
int *h_time,*dev_time;
a=(float *)malloc(sizeof(float)*N);
h_time=(int *)malloc(sizeof(int)*1);
cudaMalloc((void**)&dev_a,N*sizeof(float));
cudaMalloc((void**)&dev_time,1*sizeof(int));
*h_time = (int)time(NULL);
cudaMemcpy(dev_time,h_time,1*sizeof(int),cudaMemcpyDeviceToHost);
kernel<<>>(dev_a,dev_time);
cudaMemcpy(a,dev_a,N*sizeof(float),cudaMemcpyHostToDevice);
for(int i=0;i<N;i++)
printf("%f %d\n",a[i],i);
system("pause");
return 1;
}
@孤独流浪者
看了一下代码,虽然include等有“<>”的部分被上传的时候隐藏掉了不清楚完整的源代码,8过问题似乎有可能出在变量类型上w curand生成的结果和C的random不太一样,是0到1范围内的小数(float),直接带入到int的i里面自然会出现问题;如果无论如何都需要整数的随机量的话,可以参照这里评论的2楼:
http://aresio.blogspot.jp/2011/05/cuda-random-numbers-inside-kernels.html
@星野恵瑠
嗯 我这里是想在每个线程中产生一个随机数 然后放在共享内存中,然后在把所有线程中的随机数给拷贝到内存中 最终显示在屏幕上。嗯 这里是用的float类型 可是还是显示不对 你给的那个网址是国外的么?我这边打不开 头文件是下面这些
stdio.h
malloc.h
cuda_runtime.h
math.h
stdlib.h
time.h
curand.h
curand_kernel.h
请问您的邮箱地址是多少?我是新手,所以可能些关于CUDA的问题想问问你。可以吗?
@孤独流浪者
邮箱地址是shonetesmith$gmail.com,8过最近偶也各种忙不一定抽得出时间w
@星野恵瑠
嗯 没关系 我给你发了邮件 麻烦查收下 谢谢