c++ - 尽管 CudaSuccess,CUDA cudaMemCpy 似乎没有复制

标签 c++ cuda

我刚刚开始使用 CUDA,这是我的第一个项目。我已经搜索过这个问题,虽然我注意到其他人也有类似的问题,但没有任何建议似乎与我的具体问题相关或对我的情况没有帮助。

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

以下是流程的简要概述:

  1. 创建 X 和 Y 位置、速度、加速度 vector 。
  2. 在 GPU 上创建相同的 vector 并复制值
  3. 在一个循环中:(i) 计算迭代的加速度,(ii) 将加速度应用于速度和位置,以及 (iii) 将位置复制回主机以供显示。

(显示还没有实现,我会稍后做)

暂时不用担心加速度计算函数,这里是更新函数:

__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];
    }
}

下面是主要方法中的一些代码:

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 时选择不安装捆绑的驱动程序,因为它们比我拥有的旧。

最佳答案

这行不通:

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

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

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

关于c++ - 尽管 CudaSuccess,CUDA cudaMemCpy 似乎没有复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28489768/

相关文章:

c - CUDA 中的 tex1Dfetch 和流

c++ - 我如何将cuda与nodejs一起使用

c++ - C++ 中的 dyn_cast 与 dynamic_cast

c++ - gettext - 加载本地目录

c++ - C++11 中的 move 语义

c++ - 在 Windows 上的 Qt Creator 中编译 Cuda 代码

c - 启动多个 CUDA 内核是否需要返回每个内核的主机?

c - 将数据从设备复制到主机是否有任何限制?

c++ - 动态生成和安全使用spsc_queues

c++ - 未定义对 linux makefile 中函数的引用