Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
做而不做';不能在CUDA内核中工作_C_Cuda_Gpgpu - Fatal编程技术网

做而不做';不能在CUDA内核中工作

做而不做';不能在CUDA内核中工作,c,cuda,gpgpu,C,Cuda,Gpgpu,好吧,我是CUDA的新手,我有点迷路了,真的迷路了 我试图用蒙特卡罗方法计算π,最后我只得到一个加法,而不是50 我不想因为调用内核而“做一段时间”,因为它太慢了。我的问题是,我的代码不会循环,它在内核中只执行一次 而且,我希望所有线程都访问相同的niter和pi,因此当一些线程命中计数器时,所有其他线程都会停止 #define SEED 35791246 __shared__ int niter; __shared__ double pi; __global__ void calcular

好吧,我是CUDA的新手,我有点迷路了,真的迷路了

我试图用蒙特卡罗方法计算π,最后我只得到一个加法,而不是50

我不想因为调用内核而“做一段时间”,因为它太慢了。我的问题是,我的代码不会循环,它在内核中只执行一次

而且,我希望所有线程都访问相同的niter和pi,因此当一些线程命中计数器时,所有其他线程都会停止

#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吗每个线程的te
    niter
    变量,或者它们都应该更新同一个变量?您希望它们计算单独的
    pi
    变量吗?还是希望它们都在同一个变量上工作?这里还有一个关于CUDA中pi演算的教程,
    cudaMemcpy..Symbol
    不用于
    \uuuuuuuuuuuuuuuuuuuuuuuuuu共享\uuuuuuuuuu
    变量还需要在循环之外为你的随机数生成器植入种子。哎,谢谢!它真的解决了我的问题。同时也感谢批评者,他们总是受欢迎的。