我刚刚开始使用CUDA,这是我的第一个项目。我已经对这个问题进行了搜索,虽然我注意到其他人也遇到过类似的问题,但这些建议似乎与我的具体问题无关,或者在我的案例中有所帮助。
作为练习,我正在尝试使用CUDA编写n体仿真。在这个阶段,我不感兴趣我的具体实现是否有效,我只是在找一些有用的东西,我可以稍后改进它。我还需要稍后更新代码,一旦它正常工作,就可以处理我的SLI配置。
以下是该流程的简要概述:
(显示尚未实现。我稍后会这样做)
现在不用担心加速度计算功能,这里是更新功能:
__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
没有复制数据。
所有cudaMalloc
和cudaMemcpy
来电都会返回cudaScuccess
。
Here是完整代码的PasteBin链接。它应该相当简单,因为各种数组都有很多重复。
就像我说的那样,我之前从未编写过CUDA代码,而且我是根据来自NVidia的#2 CUDA示例视频编写的,其中该人编写并行数组加法代码。我不确定它是否有任何区别,但我使用2x GTX970与最新的NVidia驱动程序和CUDA 7.0 RC,我选择在安装CUDA时不安装捆绑的驱动程序,因为它们比我的旧。 / p>
答案 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)。从性能角度来看,这通常也是可取的。