0

私はレイトレーシングを行うためのcudaプログラムを構築しようとしていますが、以下のコードがあります。

void build_world(World *w, RGBAColor* buffer){  
w->vp = (ViewPlane*) malloc(sizeof(ViewPlane));

w->vp->hres = 512;
w->vp->vres = 512;
w->vp->buffer = buffer;
w->vp->s = 1;

ViewPlane *viewplane;
cudaMalloc(&viewplane,sizeof(ViewPlane)); //return cudaSuccess but pointer still NULL
cudaMemcpy(viewplane,w->vp,sizeof(ViewPlane),cudaMemcpyHostToDevice);
free(w->vp);
w->vp = viewplane;

cudaMalloc(&(w->background_color),sizeof(RGBAColor)); //return cudaSuccess but pointer still NULL
*(w->background_color) = black;  //Memory access error

cudaMalloc(&(w->sphere),sizeof(Sphere));  //return cudaSuccess but pointer still NULL
w->sphere->center = Point3D(0.0,0.0,0.0);
w->sphere->radius = 300;
}

World * wは静的グローバルポインタであり、グローバルメモリにあります。私の問題は、デバイスのメモリにメモリを割り当てることができないことです。すべての「cudaMalloc」呼び出しがほとんどの時間機能しません。


私は@RobertCrovellaがコメントで提案したことを次のように行います:

void build_world(World *w, RGBAColor* buffer){

    checkCudaErrors( cudaMalloc(&(w->vp),sizeof(ViewPlane)));
    getLastCudaError("viewplane allocate failed");

    w->vp->hres = 512;  //memory access errors occurs here
    w->vp->vres = 512;
    w->vp->buffer = buffer;
    w->vp->s = 1;       

    checkCudaErrors( cudaMalloc(&(w->background_color),sizeof(RGBAColor)));
    getLastCudaError("background allocate failed");
    *(w->background_color) = black;

    checkCudaErrors( cudaMalloc(&(w->sphere),sizeof(Sphere)));
    getLastCudaError("sphere allocate failed");

    w->sphere->center = Point3D(0.0,0.0,0.0);
    w->sphere->radius = 300;
}

一度は機能します...cudaMallocAPIは、そうでない場合でも「cudaSuccess」を返します。

構造の定義は次のとおりです。

typedef float3 Point3D;
typedef uchar4 RGBAColor;
struct Sphere{
    Point3D center;
    float radius;
};
struct ViewPlane{
public:
    int hres;
    int vres;
    float s;
    //float gamma;
    //float inv_gamma;

    RGBAColor *buffer;

};
struct World{
public:

    ViewPlane *vp;
    RGBAColor *background_color;
    Sphere *sphere;

};

@RobertCrovellaが以下の回答で言及している問題を検討した後、build_worldの3番目のバージョンを次に示します。

struct World{
public:

    ViewPlane *vp;
    RGBAColor background_color;
    Sphere *sphere;

};
void build_world(World *w, RGBAColor* buffer){  
    World *h_world;
    h_world = (World*)malloc(sizeof(World));

    ViewPlane *h_vp = (ViewPlane*)malloc(sizeof(ViewPlane));
    h_vp->hres = 512;
    h_vp->vres = 512;
    h_vp->buffer = buffer;
    h_vp->s = 1;        
    checkCudaErrors( cudaMalloc(&(h_world->vp),sizeof(ViewPlane)));
    getLastCudaError("viewplane allocate failed");
    checkCudaErrors( cudaMemcpy(h_world->vp,h_vp,sizeof(ViewPlane),cudaMemcpyHostToDevice));
    getLastCudaError("viewplane memory copy failed");

    h_world->background_color = black;

    Sphere *h_sphere = (Sphere*)malloc(sizeof(Sphere));
    h_sphere->center = Point3D(0.0,0.0,0.0);
    h_sphere->radius = 300;
    checkCudaErrors( cudaMalloc(&(h_world->sphere),sizeof(Sphere)));
    getLastCudaError("sphere allocate failed");
    checkCudaErrors( cudaMemcpy(h_world->sphere,h_sphere,sizeof(Sphere),cudaMemcpyHostToDevice));
    getLastCudaError("sphere memory copy failed");

    checkCudaErrors( cudaMalloc( &w , sizeof(World)));
    getLastCudaError( "world allocate failed" );
    checkCudaErrors( cudaMemcpy(w,h_world,sizeof(World),cudaMemcpyHostToDevice));
    getLastCudaError("world memory copy failed");

    free(h_world);free(h_vp);free(h_sphere);    
}

今回は、すべてのcudaMemcpy呼び出しが機能するわけではありません。この関数の最後まで実行すると、h_vpandの値h_sphereは適切です。デバイスのmomeryの領域を指していますが、間違った値が含まれていますh_world->vp。正しい値がありません。含まれるすべてのポインタは0x00000000です。h_world->spherew

4

1 に答える 1

0

build_worldこの質問は、私が追加するように依頼したエラーチェックだけでなく、重要な点で異なる2つの大幅に異なるバージョンを投稿したため、正式に「混乱」になりました。私はそれらを見ながらいくつかの問題に対処しようとしますが、私の理解はあなたの投稿の混乱によって曇っています。

  • *w渡しているポインタbuild_worldがすでにデバイスポインタである(つまり、で割り当てられているcudaMalloc)場合、これはあなたが言っていることのように見えますが、これはどれも機能しません。デバイス上にデータ構造を作成することは、デバイス上にある他のデータ構造へのポインターも含みますが、やや直感的ではないプロセスです。デバイス上にすでに存在するポインターを渡すことはできません(つまり、で作成された領域の一部です。代わりに、ホスト上に並列のポインターセットを作成し、これらのポインターを個別に作成してから、ポインター値を適切な領域にコピーする必要があります。デバイスのデータ構造で、cudaMemcpyを使用します。私が参照している別の例を確認するには、ここを参照してください。cudaMalloccudaMalloccudaMalloc
  • ホストコードでデバイスポインタを逆参照することはできません。例えば:

    w->vp->hres = 512;
    

    wまたw->vpはがで設定されたポインタである場合cudaMalloc、上記の操作は無効です。代わりに、ホスト上に並列データ構造を作成し、そこに値を設定してcudaMemcpyから、ホストからデバイスに移動する必要があります。

    h_vp->hres = 512;
    cudaMemcpy(d_vp, h_vp, sizeof(vp_struct), cudaMemcpyHostToDevice);
    

    この簡略化された説明では、上記の最初のポイントで述べた問題について詳しく説明していることに注意してください。

  • 何度も何度も呼び出す場合、同じポインタを渡す場合build_worldは、正しく使用していることを確認する必要があります。cudaFree*w

編集:build_world私は、残りの問題を修正する必要があるサンプルコードを作成することを選択したの3番目のバージョンの追加の投稿に応えて:

#include <stdio.h>
#include <vector_functions.h>

#define black make_uchar4(4,3,2,1)
#define white make_uchar4(0,1,2,3)

#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)

typedef float3 Point3D;
typedef uchar4 RGBAColor;
struct Sphere{
    Point3D center;
    float radius;
};
struct ViewPlane{
public:
    int hres;
    int vres;
    float s;
    //float gamma;
    //float inv_gamma;

    RGBAColor *buffer;

};

struct World{
public:

    ViewPlane *vp;
    RGBAColor background_color;
    Sphere *sphere;

};

__global__ void my_kernel(World *w){

  printf("w->vp->hres = %d\n", w->vp->hres);
  printf("w->background_color.y = %d\n", w->background_color.y);
  printf("w->sphere->radius = %f\n", w->sphere->radius);
  printf("w->vp->buffer->y = %d\n", w->vp->buffer->y);

}


void build_world(World **w, RGBAColor* buffer){
    World *h_world;
    h_world = (World*)malloc(sizeof(World));

    ViewPlane *h_vp = (ViewPlane*)malloc(sizeof(ViewPlane));
    h_vp->hres = 512;
    h_vp->vres = 512;
    h_vp->s = 1;
    cudaMalloc((void **)&(h_vp->buffer), sizeof(RGBAColor));
    cudaCheckErrors("viewplane RGBAColor allocate failed");
    cudaMemcpy(h_vp->buffer, buffer, sizeof(RGBAColor), cudaMemcpyHostToDevice);
    cudaCheckErrors("viewplane RGBAColor copy failed");

    cudaMalloc((void **)&(h_world->vp),sizeof(ViewPlane));
    cudaCheckErrors("viewplane allocate failed");
    cudaMemcpy(h_world->vp,h_vp,sizeof(ViewPlane),cudaMemcpyHostToDevice);
    cudaCheckErrors("viewplane memory copy failed");

    h_world->background_color = black;

    Sphere *h_sphere = (Sphere*)malloc(sizeof(Sphere));
    h_sphere->center = (Point3D) make_float3(0.0,0.0,0.0);
    h_sphere->radius = 300;
    cudaMalloc((void **)&(h_world->sphere),sizeof(Sphere));
    cudaCheckErrors("sphere allocate failed");
    cudaMemcpy(h_world->sphere,h_sphere,sizeof(Sphere),cudaMemcpyHostToDevice);
    cudaCheckErrors("sphere memory copy failed");

    cudaMalloc((void **)w , sizeof(World));
    cudaCheckErrors( "world allocate failed" );
    cudaMemcpy(*w,h_world,sizeof(World),cudaMemcpyHostToDevice);
    cudaCheckErrors("world memory copy failed");

    free(h_world);free(h_vp);free(h_sphere);
}



int main(){

   World *d_w;
   RGBAColor my_buffer = white;

   build_world(&d_w, &my_buffer);
   my_kernel<<<1,1>>>(d_w);
   cudaDeviceSynchronize();
   cudaCheckErrors("kernel fail");
   return 0;
}

このコードは次のコマンドでコンパイルできますnvcc -arch=sm_20 -o t98 t98.cu

このコードをコンパイルして実行すると、エラーは発生せず、次の出力が表示されます。

$ ./t98
w->vp->hres = 512
w->background_color.y = 3
w->sphere->radius = 300.000000
w->vp->buffer->y = 1
$ 
于 2013-03-23T15:31:41.040 に答える