蒙特卡洛在库达横扫

时间:2014-04-12 22:43:10

标签: c++ cuda gpgpu montecarlo

我在Cuda有一个蒙特卡罗步骤,我需要帮助。我已经编写了序列代码,它按预期工作。我们说我有256个粒子,存储在

vector< vector<double> > *r;

r中的每个i都有(x,y)分量,两者都是双重的。这里,r是粒子的位置。

现在,在CUDA中,我应该在Host中分配此向量,并将其发送到Device。一旦进入设备,这些粒子需要相互作用。每个线程都应该运行蒙特卡罗扫描。如何使用cudaMalloc分配内存,引用/解除引用指针,cudaMalloc用于实现全局/共享,... - 我只是无法绕过它。

这是我的记忆分配当前所看到的内容::

cudaMalloc((void**)&r, (blocks*threads)*sizeof(double));    
CUDAErrorCheck();
kernel <<<blocks, threads>>> (&r, randomnums);
cudaDeviceSynchronize();
CUDAErrorCheck();
cudaMemcpy(r, blocks*threads*sizeof(double), cudaMemcpyDeviceToHost);

上面的代码是在马铃薯级别。我猜,我不知道该做什么 - 甚至在概念上。我的主要问题是分配内存,并将信息传递给设备和设备。主办。需要分配向量r,从主机复制到设备,在设备中对其执行某些操作,然后将其复制回主机。任何帮助/&#34;指针&#34;非常感谢。

1 个答案:

答案 0 :(得分:2)

您的“马铃薯级别”代码表明对CUDA的普遍缺乏了解,包括但不限于r数据的管理。我建议您通过利用一些可用的教育资源来增加您对CUDA的了解,然后了解至少一个基本的CUDA代码,例如vector add sample。然后,您将能够更好地构建问题并理解您收到的答案。一个例子:

这几乎没有意义:

    cudaMalloc((void**)&r, (blocks*threads)*sizeof(double));    
    CUDAErrorCheck();
    kernel <<<blocks, threads>>> (&r, randomnums);

您可能不知道一个非常基本的概念,即数据必须先传输到设备(通过cudaMemcpy)才能被GPU内核使用,否则您不必费心去写“马铃薯”水平“完全没有任何意义的代码 - 这对我来说在写一个明智的问题时缺乏努力。此外,无论r是什么,将&r传递给cuda内核都没有意义,我不这么认为。

关于如何来回移动r的问题:

  1. 解决问题的第一步是将r位置数据重新设置为GPU内核可轻松使用的内容。一般来说,vector对普通的CUDA代码并没有那么有用,vector< vector< > >甚至更少。如果你有指针浮动(*r)甚至更少。因此,将您的位置数据展平(复制)为一个或两个动态分配的double的一维数组:

    #define N 1000 
    ...
    vector< vector<double> > r(N);
    ...
    double *pos_x_h, *pos_y_h, *pos_x_d, *pos_y_d;
    pos_x_h=(double *)malloc(N*sizeof(double));
    pos_y_h=(double *)malloc(N*sizeof(double));
    for (int i = 0; i<N; i++){
      vector<double> temp = r[i];
      pos_x_h[i] = temp[0];
      pos_y_h[i] = temp[1];}
    
  2. 现在,您可以为设备上的数据分配空间并将数据复制到设备:

    cudaMalloc(&pos_x_d, N*sizeof(double));
    cudaMalloc(&pos_y_d, N*sizeof(double));
    cudaMemcpy(pos_x_d, pos_x_h, N*sizeof(double), cudaMemcpyHostToDevice);
    cudaMemcpy(pos_y_d, pos_y_h, N*sizeof(double), cudaMemcpyHostToDevice);
    
  3. 现在您可以将位置数据正确传递给内核:

    kernel<<<blocks, threads>>>(pos_x_d, pos_y_d, ...);
    
  4. 在内核之后将数据重新复制回来 反向上述步骤。这将帮助您入门:

    cudaMemcpy(pos_x_h, pos_x_d, N*sizeof(double), cudaMemcpyDeviceToHost);
    cudaMemcpy(pos_y_h, pos_y_d, N*sizeof(double), cudaMemcpyDeviceToHost);
    
  5. 皮猫的方法有很多种,当然,以上只是一个例子。但是,上述数据组织非常适合于内核/线程策略,该策略分配一个线程来处理一个(x,y)位置对。