CUDA передача пользовательской структуры в ядро не удалось

0

Вот моя проблема. У меня есть следующая структура в моем kernel.h.

struct   __Q_VECTOR__{
    double* Data;       
    int     Dimension;  
    int     Cluster;    
};

typedef struct __Q_VECTOR__     VQ_VECTOR;

В kernel.cu меня есть следующий код

int main(void){
 int L = 3, //.Data length
    N = 100;

VQ_VECTOR   *A,
            *device_VQ_VECTOR;

cudaError_t cudaStatus;

A =   (VQ_VECTOR*)malloc(N*sizeof(VQ_VECTOR));
for(int i=0; i<N; i++){
    VQ_VECTOR a;
    a.Data = (double*)malloc(L*sizeof(double));;
    a.Cluster   =   1;
    a.Dimension =   L;
    for(int j=0; j<L; j++)
        a.Data[j]=i*j;

    A[i] = a;
}

//Prinf of all the elements of A
for(int i=0; i<2; i++){
    printf("\nA[%d]={");
    for(int j=0; j<L; j++)
        printf("%.3f",A[i].Data[j]);
    printf("}");
}

printf("\n\n");
//I Allocate and Copy data from A to device_VQ_VECTORon the GPU memory

cudaDeviceReset();
cudaStatus = cudaMalloc((void**)&device_VQ_VECTOR, N*sizeof(VQ_VECTOR));
cudaStatus = cudaMemcpy(device_VQ_VECTOR, A, N*sizeof(VQ_VECTOR), cudaMemcpyHostToDevice);
cudaPrintfInit();
testKernel<<<N,1>>>(device_VQ_VECTOR, N);//to test and see on a sigle thread
cudaPrintfDisplay(stdout, true);
cudaPrintfEnd();
cudaStatus = cudaGetLastError();
if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "\n testKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        return 1;
}
cudaStatus = cudaMemcpy(A, device_VQ_VECTOR, N*sizeof(VQ_VECTOR), cudaMemcpyDeviceToHost);
cudaStatus = cudaGetLastError();
if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "\n testKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        return 1;
}
for(int i=0; i<2; i++){
    printf("\nA[%d]={");
    for(int j=0; j<L; j++)
        printf("%.3f",A[i].Data[j]);
    printf("}");
}
cudaFree(device_VQ_VECTOR);
 return 0;

}

когда я строю, иногда он ничего не печатает, иногда он работает.
что не так в моем коде? Может быть вызвано

cudaStatus = cudaMalloc((void**)&device_VQ_VECTOR, N*sizeof(VQ_VECTOR));
cudaStatus = cudaMemcpy(device_VQ_VECTOR, A, N* sizeof(VQ_VECTOR), cudaMemcpyHostToDevice);

Помоги пожалуйста!

  • 0
    Я пробовал cudaStatus = cudaMalloc((void**)&device_VQ_VECTOR, N* sizeof(VQ_VECTOR)); for(int i=0; i<N; i++) cudaMalloc((void**)&(device_VQ_VECTOR[i].Data), X[i].nDimension * sizeof(double)); без успеха тоже
  • 1
    Вы выделяете память для data ? Добавьте это к вопросу. И, пожалуйста, опубликуйте полный скомпилированный пример, у которого явно есть синтаксические ошибки.
Показать ещё 4 комментария
Теги:
cuda

1 ответ

1

Это не может работать, потому что массивы выделяются отдельно и не копируются в память устройства. Вы также должны выделить их на устройстве и сделать полную копию. Чтобы усугубить ситуацию, вы не можете напрямую обращаться к памяти устройства со стороны хоста (иначе, чем cudaMemcpy), поэтому вы не можете использовать, например, cudaMalloc(&device_VQ_VECTOR[i].Data,...) (он выйдет из cudaMalloc(&device_VQ_VECTOR[i].Data,...)).

Вот пример кода. Для простоты он удаляет A[i].Data а затем повторно создает их. Это не слишком хорошо, но это пойдет.

struct   __Q_VECTOR__{
    double* Data;       
    int     Dimension;  
    int     Cluster;    
};

typedef struct __Q_VECTOR__     VQ_VECTOR;

__global__ void testKernel(VQ_VECTOR *X, int N){
    int i= blockIdx.x*blockDim.x + threadIdx.x;
    cuPrintf("\n testKernel entrance by the global threadIdx= %d\n", i);
    for(int k=0; k<X[i].Dimension; k++)
        cuPrintf("%2.2f, ",X[i].Data[k]);
    cuPrintf("\n");
}

int main(void){
    int L = 3, //.Data length
        N = 100;

    VQ_VECTOR   *A,
                *device_VQ_VECTOR;

    cudaError_t cudaStatus;

    A =   (VQ_VECTOR*)malloc(N*sizeof(VQ_VECTOR));
    for(int i=0; i<N; i++){
        VQ_VECTOR a;
        a.Data = (double*)malloc(L*sizeof(double));;
        a.Cluster   =   1;
        a.Dimension =   L;
        for(int j=0; j<L; j++)
            a.Data[j]=(1+i)*(1+j);

        A[i] = a;
    }

    //Prinf of all the elements of A
    for(int i=0; i<2; i++){
        printf("\nA[%d]={", i);
        for(int j=0; j<L; j++)
            printf("%.3f",A[i].Data[j]);
        printf("}\n");
    }

    printf("\n\n");
    //I Allocate and Copy data from A to device_VQ_VECTORon the GPU memory

    cudaDeviceReset();
    cudaStatus = cudaMalloc((void**)&device_VQ_VECTOR, N*sizeof(VQ_VECTOR));
    cudaStatus = cudaMemcpy(device_VQ_VECTOR, A, N*sizeof(VQ_VECTOR), cudaMemcpyHostToDevice);

    for(int i = 0; i != N; ++i) {
        /* can't access device_VQ_VECTOR[i].Data directly from host-side,
         * working around it with proxy variable */
        double *out;
        cudaMalloc(&out, L*sizeof(double));
        cudaMemcpy(out, A[i].Data, L*sizeof(double),
                cudaMemcpyHostToDevice);
        cudaMemcpy(&device_VQ_VECTOR[i].Data, &out, sizeof(void*),
                cudaMemcpyHostToDevice);

        // will re-allocate later, for simplicity sake
        free(A[i].Data);
    }

    cudaPrintfInit();
    testKernel<<<N,1>>>(device_VQ_VECTOR, N);//to test and see on a sigle thread
    cudaPrintfDisplay(stdout, true);
    cudaPrintfEnd();
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "\n testKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        return 1;
    }
    cudaStatus = cudaMemcpy(A, device_VQ_VECTOR, N*sizeof(VQ_VECTOR), cudaMemcpyDeviceToHost);
    for(int i = 0; i != N; ++i) {
        // allocate array, copy data
        double *array = (double*)malloc(L*sizeof(double));
        cudaMemcpy(array, A[i].Data, L*sizeof(double),
                cudaMemcpyDeviceToHost);

        // assign new array to A[i]
        A[i].Data = array;
    }
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "\n testKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        return 1;
    }
/*  for(int i=0; i<2; i++){
        printf("\nA[%d]={", i);
        for(int j=0; j<L; j++)
            printf("%.3f",A[i].Data[j]);
        printf("}\n");
    }*/
    cudaFree(device_VQ_VECTOR);

    // don't forget to free A and all its Data

    return 0;
}

Часть выхода будет (она огромная, я не хочу размещать слишком много):

[2, 0]: 3.00, [18, 0]: 19.00, [22, 0]: 23.00, [16, 0]: 17.00,
[24, 0]: 25.00, [19, 0]: 20.00, [4, 0]: 5.00, [23, 0]: 24.00,
[3, 0]: 4.00, [5, 0]: 6.00, [13, 0]: 14.00, [1, 0]: 2.00,
[10, 0]: 11.00, [6, 0]: 7.00, [14, 0]: 15.00, [0, 0]: 1.00, [20, 0]:
  • 0
    Спасибо, но в результатах, все VQ_VECTOR элементы device_VQ_VECTOR массива указателей имеют Data значение 0 . Я пытался напечатать Data элементов device_VQ_VECTOR[i] и все значения устанавливаются в 0. Вот мой модифицирована global функция , которую можно заменить , чтобы проверить
  • 0
    Не печатайте ничего, кроме 0. Кажется, что deviceQV_VECTOR не содержит истинных значений
Показать ещё 15 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню