おそらく、完全な簡単な例を含める必要があります。(上記のコードをコンパイルして単独で実行すると、Linuxでは2番目のcudaMalloc操作でセグメンテーション違反が発生します)。私が見る1つの問題は、最初のステップでデバイスメモリにパーティクルオブジェクトを割り当てたため、_w
ポインタを割り当てるときに、すでにデバイスメモリにあるcudaMallocにポインタを渡していることです。ホストベースのポインタをcudaMallocに渡すことになっています。このポインタは、デバイス(グローバル)メモリの割り当てられた領域に割り当てられます。
私がyoruの例で見たものに一致すると思う1つの可能な解決策は次のとおりです。
#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で有効です)。
別のアプローチは、デバイス側に_wポインタを割り当てることです。これはあなたの目的にも役立つかもしれません。
上記のすべては、cc2.0以上を想定しています。
ここで説明するのと同様の方法を使用すると、ループで実行されるデバイス側の割り当てを単一の割り当てにまとめることができる場合があります。
cudaMalloc(&(w[0]), nParticles*300*sizeof(double));
cudaCheckErrors("cudaMalloc2 fail");
cudaMemcpy(&(dev_p[0]._w), &(w[0]), sizeof(double *), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy1 fail");
for( int i = 1; i < nParticles; i++){
w[i] = w[i-1] + 300;
cudaMemcpy(&(dev_p[i]._w), &(w[i]), sizeof(double *), cudaMemcpyHostToDevice);
cudaCheckErrors("cudaMemcpy1 fail");
}
操作はcudaMemcpy
引き続き個別に実行する必要があります。