尽管CudaSuccess,CUDA cudaMemCpy似乎并未复制

时间:2015-02-12 23:20:52

标签: c++ cuda

我刚刚开始使用CUDA,这是我的第一个项目。我已经对这个问题进行了搜索,虽然我注意到其他人也遇到过类似的问题,但这些建议似乎与我的具体问题无关,或者在我的案例中有所帮助。

作为练习,我正在尝试使用CUDA编写n体仿真。在这个阶段,我不感兴趣我的具体实现是否有效,我只是在找一些有用的东西,我可以稍后改进它。我还需要稍后更新代码,一旦它正常工作,就可以处理我的SLI配置。

以下是该流程的简要概述:

  1. 创建X和Y位置,速度,加速度矢量。
  2. 在GPU上创建相同的向量并跨
  3. 复制值
  4. 在循环中:(i)计算迭代的加速度,(ii)将加速度应用于速度和位置,以及(iii)将位置复制回主机以供显示。
  5. (显示尚未实现。我稍后会这样做)

    现在不用担心加速度计算功能,这里是更新功能:

    __global__ void apply_acc(double* pos_x, double* pos_y, double* vel_x, double* vel_y, double* acc_x, double* acc_y, int N)
    {
        int i = threadIdx.x;
    
        if (i < N);
        {
            vel_x[i] += acc_x[i];
            vel_y[i] += acc_y[i];
    
            pos_x[i] += vel_x[i];
            pos_y[i] += vel_y[i];
        }
    }
    

    以下是main方法中的一些代码:

    cudaError t;
    
    t = cudaMalloc(&d_pos_x, N * sizeof(double));
    t = cudaMalloc(&d_pos_y, N * sizeof(double));
    t = cudaMalloc(&d_vel_x, N * sizeof(double));
    t = cudaMalloc(&d_vel_y, N * sizeof(double));
    t = cudaMalloc(&d_acc_x, N * sizeof(double));
    t = cudaMalloc(&d_acc_y, N * sizeof(double));
    
    t = cudaMemcpy(d_pos_x, pos_x, N * sizeof(double), cudaMemcpyHostToDevice);
    t = cudaMemcpy(d_pos_y, pos_y, N * sizeof(double), cudaMemcpyHostToDevice);
    t = cudaMemcpy(d_vel_x, vel_x, N * sizeof(double), cudaMemcpyHostToDevice);
    t = cudaMemcpy(d_vel_y, vel_y, N * sizeof(double), cudaMemcpyHostToDevice);
    t = cudaMemcpy(d_acc_x, acc_x, N * sizeof(double), cudaMemcpyHostToDevice);
    t = cudaMemcpy(d_acc_y, acc_y, N * sizeof(double), cudaMemcpyHostToDevice);
    
    while (true)
    {
        calc_acc<<<1, N>>>(d_pos_x, d_pos_y, d_vel_x, d_vel_y, d_acc_x, d_acc_y, N);
        apply_acc<<<1, N>>>(d_pos_x, d_pos_y, d_vel_x, d_vel_y, d_acc_x, d_acc_y, N);
    
        t = cudaMemcpy(pos_x, d_pos_x, N * sizeof(double), cudaMemcpyDeviceToHost);
        t = cudaMemcpy(pos_y, d_pos_y, N * sizeof(double), cudaMemcpyDeviceToHost);
    
        std::cout << pos_x[0] << std::endl;
    }
    

    每个循环cout都写入相同的值,无论它是在原始创建位置数组时设置的随机值。如果我将apply_acc中的代码更改为:

    __global__ void apply_acc(double* pos_x, double* pos_y, double* vel_x, double* vel_y, double* acc_x, double* acc_y, int N)
    {
        int i = threadIdx.x;
    
        if (i < N);
        {
            pos_x[i] += 1.0;
            pos_y[i] += 1.0;
        }
    }
    

    然后它仍然给出相同的值,因此没有调用apply_acc或者cudaMemcpy没有复制数据。

    所有cudaMalloccudaMemcpy来电都会返回cudaScuccess

    Here是完整代码的PasteBin链接。它应该相当简单,因为各种数组都有很多重复。

    就像我说的那样,我之前从未编写过CUDA代码,而且我是根据来自NVidia的#2 CUDA示例视频编写的,其中该人编写并行数组加法代码。我不确定它是否有任何区别,但我使用2x GTX970与最新的NVidia驱动程序和CUDA 7.0 RC,我选择在安装CUDA时不安装捆绑的驱动程序,因为它们比我的旧。 / p>

1 个答案:

答案 0 :(得分:3)

这不起作用:

const int N = 100000;
...
calc_acc<<<1, N>>>(...);
apply_acc<<<1, N>>>(...);

内核启动配置(<<<...>>>)的第二个参数是每个块参数的线程数。它仅限于512或1024,具体取决于您的编译方式。这些内核不会启动,并且需要使用正确的CUDA error checking来捕获它产生的错误类型。只需查看后续CUDA API函数的返回值,就不会表明存在此类错误(这就是您随后看到cudaSuccess的原因)。

关于概念本身,我建议您了解有关CUDA thread and block hierarchy的更多信息。要启动大量线程,您需要使用内核启动配置的两个参数(即前两个参数中的任何一个应为1)。从性能角度来看,这通常也是可取的。