CUDA果然好厉害!8过也各种无法理解ww

也许有人还记得咱曾经做过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

Author: 星野恵瑠

Mac user, Niji-Ota, Chinese, Now working in Japan at MAGES. Inc., Future's aim is that one day my name can be listed in Wikipedia

29 thoughts on “CUDA果然好厉害!8过也各种无法理解ww”

  1. cuda很不错呢,下个学期打算修cuda的课

    同样感觉是随机函数生成伪随机时种子的问题

  2. 第一次看到CUDA的代码。。。。

    不行不行。。。。看到千反田捕获奉太郎,ヾ(≧▽≦*)o。笑死了=w=

    窗口都把壁纸挡住啦!QvQ

  3. 咱最近是除了Objective-C外,几乎就没有看其他编程语言了…
    大学毕业前夕也是各种荒废的时候啊,没有看书的动力…
    在这次七月新番当中,摇曳百合、TARI TARI最期待了…
    话说车左边的标牌上的字是什么意思啊?

    ps:用Siri的Dictation输入真的是好方便啊…

  4. @conanshang
    妇产科的标牌啊 (=v=o)

    @itorr
    压视频神马的好怀念 (^^;) 最近都好懒了懒得压视频了

    @linfcstmr’助手廚
    怎么了 (!!!!)

    @Bee君
    千反田恵瑠最美了 (o>v<o)

    @Leyeang
    咱不就正在动漫的液界里面么 (!!!!)

    @zym9
    似乎很方便!8过是收费的orz嘛反正是毕业研究用的 (^^;)

    @天羽
    Newtype的姊妹志娘type (:D)

    @maplebeats
    嘛肯定有什么不一样的8过咱实在无法想象是啥不一样 (-w-;)

    @陈少举
    咱不是大大 (!!!!)

    @bi119aTe5hXk
    写的时候当然圈了问题是WP还是照样不显示 (=v=o)

    @萌名雪
    现在可以显示了 (XD)

    @keekun
    那个已经用时间和thread id初期化了 ( ̄‥ ̄)

  5. 你好 我想问您一下 我用了您代码中的一部分关于产生随机数的部分 为什么我运行后是一个负值 而且其绝对值很大 另外每一个线程所产生的随机数都相同??

  6. @星野恵瑠
    #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;
    }

  7. @孤独流浪者
    看了一下代码,虽然include等有“<>”的部分被上传的时候隐藏掉了不清楚完整的源代码,8过问题似乎有可能出在变量类型上w curand生成的结果和C的random不太一样,是0到1范围内的小数(float),直接带入到int的i里面自然会出现问题;如果无论如何都需要整数的随机量的话,可以参照这里评论的2楼:
    http://aresio.blogspot.jp/2011/05/cuda-random-numbers-inside-kernels.html

  8. @星野恵瑠
    嗯 我这里是想在每个线程中产生一个随机数 然后放在共享内存中,然后在把所有线程中的随机数给拷贝到内存中 最终显示在屏幕上。嗯 这里是用的float类型 可是还是显示不对 你给的那个网址是国外的么?我这边打不开 头文件是下面这些
    stdio.h
    malloc.h
    cuda_runtime.h
    math.h
    stdlib.h
    time.h
    curand.h
    curand_kernel.h
    请问您的邮箱地址是多少?我是新手,所以可能些关于CUDA的问题想问问你。可以吗?

Leave a Reply to 萌名雪 Cancel reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

(;;) (:D) (!!!!) (……) (^o^;) (==) (OoO) (=v=o) more »Note: Commenter is allowed to use '@User+blank' to automatically notify your reply to other commenter. e.g, if ABC is one of commenter of this post, then write '@ABC '(exclude ') will automatically send your comment to ABC. Using '@all ' to notify all previous commenters. Be sure that the value of User should exactly match with commenter's name (case sensitive).