假设我有这门课程:
class Particle
{
double *_w;
};
我想将Particle
的 nParticles 对象发送到我的内核。为这些对象分配空间很简单:
Particle *dev_p;
cudaStatus = cudaMalloc((void**)&dev_P, nParticles * sizeof(Particle));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
}
还假设 nParticles为100 。现在我需要为_w
对象中的每个Particle
分配 300 double 。我怎样才能做到这一点?我试过这段代码:
for( int i = 0; i < nParticles; i++){
cudaStatus = cudaMalloc((void**)&(dev_P[i]._w), 300 * sizeof(double));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!");
goto Error;
}
}
但是当我访问dev_p [i] ._ w [j]时,使用Nsight进行调试会停止。
答案 0 :(得分:6)
也许你应该包括一个完整的简单例子。 (如果我在上面编译你的代码并自己运行它,在linux上,我在第二次cudaMalloc操作时遇到了一个seg错误)。我看到的一个问题是,因为你在第一步中已经在设备内存中分配了粒子对象,所以当你去分配_w
指针时,你会传递一个指向已经在设备内存中的cudaMalloc的指针。您应该将基于主机的指针传递给cudaMalloc,然后它将分配给设备(全局)内存中的已分配区域。
我认为一个可能的解决方案符合我在yoru示例中看到的内容是这样的:
#include <stdio.h>
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
class Particle
{
public:
double *_w;
};
__global__ void test(Particle *p){
int idx=threadIdx.x + blockDim.x*blockIdx.x;
if (idx == 2){
printf("dev_p[2]._w[2] = %f\n", p[idx]._w[2]);
}
}
int main() {
int nParticles=100;
Particle *dev_p;
double *w[nParticles];
cudaMalloc((void**)&dev_p, nParticles * sizeof(Particle));
cudaCheckErrors("cudaMalloc1 fail");
for( int i = 0; i < nParticles; i++){
cudaMalloc((void**)&(w[i]), 300 * sizeof(double));
cudaCheckErrors("cudaMalloc2 fail");
cudaMemcpy(&(dev_p[i]._w), &(w[i]), sizeof(double *), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy1 fail");
}
double testval = 32.7;
cudaMemcpy(w[2]+2, &testval, sizeof(double), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy2 fail");
test<<<1, 32>>>(dev_p);
cudaDeviceSynchronize();
cudaCheckErrors("kernel fail");
printf("Done!\n");
}
这里我们在主机上创建一组单独的指针用于cudaMalloc目的,然后将这些分配的指针复制到设备以用作设备指针(这对于UVA来说是合法的)。
另一种方法是allocate the _w pointers on the device side。这也可以满足您的目的。
以上所有我假设cc 2.0或更高。
答案 1 :(得分:1)
有两种方法可以做到这一点。第一个 - 您在主机上分配内存,填充主机粒子对象数组。完成后,通过cudaMemcpy
将主机阵列复制到设备。
第二种方式 - 在Fermi及更高版本上,您可以在内核中调用malloc
,从内核填充dev_P
数组。