做而不做';不能在CUDA内核中工作
好吧,我是CUDA的新手,我有点迷路了,真的迷路了 我试图用蒙特卡罗方法计算π,最后我只得到一个加法,而不是50 我不想因为调用内核而“做一段时间”,因为它太慢了。我的问题是,我的代码不会循环,它在内核中只执行一次 而且,我希望所有线程都访问相同的niter和pi,因此当一些线程命中计数器时,所有其他线程都会停止做而不做';不能在CUDA内核中工作,c,cuda,gpgpu,C,Cuda,Gpgpu,好吧,我是CUDA的新手,我有点迷路了,真的迷路了 我试图用蒙特卡罗方法计算π,最后我只得到一个加法,而不是50 我不想因为调用内核而“做一段时间”,因为它太慢了。我的问题是,我的代码不会循环,它在内核中只执行一次 而且,我希望所有线程都访问相同的niter和pi,因此当一些线程命中计数器时,所有其他线程都会停止 #define SEED 35791246 __shared__ int niter; __shared__ double pi; __global__ void calcular
#define SEED 35791246
__shared__ int niter;
__shared__ double pi;
__global__ void calcularPi(){
double x;
double y;
int count;
double z;
count = 0;
niter = 0;
//keep looping
do{
niter = niter + 1;
//Generate random number
curandState state;
curand_init(SEED,(int)niter, 0, &state);
x = curand(&state);
y = curand(&state);
z = x*x+y*y;
if (z<=1) count++;
pi =(double)count/niter*4;
}while(niter < 50);
}
int main(void){
float tempoTotal;
//Start timer
clock_t t;
t = clock();
//call kernel
calcularPi<<<1,32>>>();
//wait while kernel finish
cudaDeviceSynchronize();
typeof(pi) piFinal;
cudaMemcpyFromSymbol(&piFinal, "pi", sizeof(piFinal),0, cudaMemcpyDeviceToHost);
typeof(niter) niterFinal;
cudaMemcpyFromSymbol(&niterFinal, "niter", sizeof(niterFinal),0, cudaMemcpyDeviceToHost);
//Ends timer
t = clock() - t;
tempoTotal = ((double)t)/CLOCKS_PER_SEC;
printf("Pi: %g \n", piFinal);
printf("Adds: %d \n", niterFinal);
printf("Total time: %f \n", tempoTotal);
}
#定义种子35791246
__共享的\uuuuu_uuuu_uuu_uu_uuu_uuu_uu_uuu_uuu_uuu_uuu_uuu;
__共享双pi;
__全局计算{
双x;
双y;
整数计数;
双z;
计数=0;
硝酸盐=0;
//继续循环
做{
硝酸盐=硝酸盐+1;
//生成随机数
库兰州;
curand_init(种子(int)niter、0和状态);
x=城市和州;
y=城市和州;
z=x*x+y*y;
如果(z代码有各种各样的问题
我建议在cuda memcheck
中使用并运行您的代码,以发现任何运行时错误。为了简洁起见,我在下面的代码中省略了正确的错误检查,但我在cuda memcheck
中运行它,以指示没有运行时错误
您对curand()
的使用可能不正确(它返回大范围的整数)。要使此代码正常工作,您需要一个介于0和1之间的浮点量。它是curand\u uniform()
由于您希望所有线程都在相同的值上工作,因此必须防止这些线程相互重叠。一种方法是使用相关变量的原子更新
不必在每次迭代中重新运行curand_init
。每个线程一次就足够了
我们不对\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu共享变量使用cudaMemcpy...Symbol操作。为了
以下是您的代码的修改版本,修复了上述大多数问题:
$ cat t978.cu
#include <curand.h>
#include <curand_kernel.h>
#include <stdio.h>
#define ITER_MAX 5000
#define SEED 35791246
__device__ int niter;
__device__ int count;
__global__ void calcularPi(){
double x;
double y;
double z;
int lcount;
curandState state;
curand_init(SEED,threadIdx.x, 0, &state);
//keep looping
do{
lcount = atomicAdd(&niter, 1);
//Generate random number
x = curand_uniform(&state);
y = curand_uniform(&state);
z = x*x+y*y;
if (z<=1) atomicAdd(&count, 1);
}while(lcount < ITER_MAX);
}
int main(void){
float tempoTotal;
//Start timer
clock_t t;
t = clock();
int count_final = 0;
int niter_final = 0;
cudaMemcpyToSymbol(niter, &niter_final, sizeof(int));
cudaMemcpyToSymbol(count, &count_final, sizeof(int));
//call kernel
calcularPi<<<1,32>>>();
//wait while kernel finish
cudaDeviceSynchronize();
cudaMemcpyFromSymbol(&count_final, count, sizeof(int));
cudaMemcpyFromSymbol(&niter_final, niter, sizeof(int));
//Ends timer
double pi = count_final/(double)niter_final*4;
t = clock() - t;
tempoTotal = ((double)t)/CLOCKS_PER_SEC;
printf("Pi: %g \n", pi);
printf("Adds: %d \n", niter_final);
printf("Total time: %f \n", tempoTotal);
}
$ nvcc -o t978 t978.cu -lcurand
$ cuda-memcheck ./t978
========= CUDA-MEMCHECK
Pi: 3.12083
Adds: 5032
Total time: 0.558463
========= ERROR SUMMARY: 0 errors
$
$cat t978.cu
#包括
#包括
#包括
#定义ITER_MAX 5000
#定义种子35791246
__仪器仪表;
__设备计数;
__全局计算{
双x;
双y;
双z;
int lcount;
库兰州;
curand_init(SEED、threadIdx.x、0和state);
//继续循环
做{
lcount=atomicAdd(&niter,1);
//生成随机数
x=曲线和均匀状态;
y=曲线和均匀状态;
z=x*x+y*y;
if(zI不想粗鲁,但我必须问您是否理解所有线程都执行内核?并且当您使用共享内存时,您需要避免争用条件和其他同步问题?您正在启动的32个线程中的每个线程)基本上是做同样的事情。这意味着当线程写入niter
和pi
时,它们可能会相互影响。此外,由于cuda 5.0,我们在cudaMemcpy..Symbol操作中不使用字符串参数。您正在启动32个线程。您希望每个线程都做什么?您想要一个separa吗每个线程的teniter
变量,或者它们都应该更新同一个变量?您希望它们计算单独的pi
变量吗?还是希望它们都在同一个变量上工作?这里还有一个关于CUDA中pi演算的教程,cudaMemcpy..Symbol
不用于\uuuuuuuuuuuuuuuuuuuuuuuuuu共享\uuuuuuuuuu
变量还需要在循环之外为你的随机数生成器植入种子。哎,谢谢!它真的解决了我的问题。同时也感谢批评者,他们总是受欢迎的。