2013-03-23 2 views
0

я Тринг построить Cuda программы, чтобы сделать лучевое, и у меня есть некоторый код ниже:cudaMalloc не работает при попытке создать пользовательский тип структуры

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

и он работает сразу ... cudaMalloc API еще возвращает "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:

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_vp и h_sphere хорошее; h_world->vp и h_world->sphere указывают на область устройства, но содержат неправильное значение; w не имеет правильного значения, весь указатель содержит 0x00000000 ...

+0

1. do [проверка ошибки cuda] (http://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime -api) во всех вызовах cuda и вызовах ядра 2. сообщать о конкретной строке, в которой происходят ошибки (-ы), и о конкретном сообщении об ошибке, которое отображается, когда вы проверяете ошибку cuda на этой строке 3. предоставлять всю соответствующую структуру/класс определения, такие как «Мир» в этом случае. –

+0

работает, когда я делаю «checkCudaErrors» ко всем «cudaMalloc», почему? – Clones1201

+0

@RobertCrovella он работает только один раз ... – Clones1201

ответ

0

Этот вопрос официально стал «беспорядком», потому что вы разместили две существенно отличающиеся версии build_world, которые отличаются важными способами, помимо просто ошибки я попросил вас добавить. Я попытаюсь решить некоторые проблемы, как я их вижу, однако мое понимание омрачено путаницей в вашей публикации.

  • Если указатель *w, что вы передаете в build_world уже указатель устройства (т.е. выделяется cudaMalloc), который, кажется, что вы говорите, то ничего из этого не будет работать. Создание структур данных на устройстве, которое также содержит указатели на другие структуры данных, которые также находятся на устройстве, является несколько неинтуитивным процессом. You не может передать указатель на cudaMalloc, который уже живет на устройстве (т.е. уже является частью области, созданной с помощью cudaMalloc). Вместо этого необходимо создать параллельный набор указателей на хосте, cudaMalloc эти указатели в отдельности, а затем скопировать указатель . значения в соответствующих регионах в структуре данных устройства, используя cudaMemcpy чтобы увидеть еще один пример того, что я имею в виду, посмотрите here
  • Вы не можете указатели разыменования устройства в коде хоста. Например:.

    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 указатель.

EDIT: В ответ на дополнительную проводку 3 версии build_world я решил создать образец код, который должен быть оставшиеся вопросами неподвижными:

#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 
$ 
+0

'World * w' сам указатель, который, как мне кажется, находится в памяти хоста, и должен указывать на область памяти устройства. Я пытаюсь выделить память устройства для указателя '* w' в' build_world', поэтому мне нужно вызвать 'cudaMalloc' для' * w' в 'build_world' ... я публикую новую версию' build_world' и это приносит еще одну проблему ... – Clones1201

+0

и спасибо за ответ. – Clones1201

+0

Ваша третья публикация 'build_world' была довольно близка к правильной. Вместо того, чтобы пытаться объяснить окончательные проблемы, я решил обновить свой ответ с помощью рабочего образца кода, который должен содержать оставшиеся проблемы. –

Смежные вопросы