CUDA копировать данные, которые динамически Malloc в ядре из памяти устройства - PullRequest
0 голосов
/ 12 сентября 2018

Я столкнулся с проблемой использования cudaMemcpy с cudaMemcpyDeviceToHost .

Существует структура, имеющая указатель int * a , которая будет выполнять функцию malloc в функции ядра.И тогда мне нужно скопировать int * a в память хоста.

Мой вопрос: я не знал, как это не может работать, используя cudaMemcpy .

Там мои коды:

#include <cuda_runtime.h>
#include <stdio.h>

typedef struct { int n, m; int *a; } myst;

__global__ void xthread(myst *st)
{
    unsigned int idx = blockIdx.x*blockDim.x + threadIdx.x;
    myst *mst = &st[idx];
    mst->n = idx;
    mst->m = idx+1;
    mst->a = (int *)malloc((mst->m)*sizeof(int));
    mst->a[0] = idx;
}


int main(int argc,char **argv)
{
    dim3 dimGrid(1);
    dim3 dimBlock(2);

    myst *mst = NULL;
    myst *hst = (myst *)malloc(2 * sizeof(myst));
    cudaMalloc(&mst, 2 * sizeof(myst));

    xthread<<<dimGrid, dimBlock>>>(mst);
    cudaDeviceSynchronize();

    cudaMemcpy(&hst[0],&mst[0],sizeof(myst),cudaMemcpyDeviceToHost);
    cudaMemcpy(&hst[1],&mst[1],sizeof(myst),cudaMemcpyDeviceToHost);

    int *pInt1 = (int *)malloc((hst[0].m)*sizeof(int)) ;
    int *pInt2 = (int *)malloc((hst[1].m)*sizeof(int)) ;

    cudaMemcpy(pInt1, hst[0].a, (hst[0].m)*sizeof(int), cudaMemcpyDeviceToHost);
    cudaMemcpy(pInt2, hst[1].a, (hst[1].m)*sizeof(int), cudaMemcpyDeviceToHost);

    printf("%d\t%d\t%d\n",hst[0].n,hst[0].m, pInt1[0]);
    printf("%d\t%d\t%d\n",hst[1].n,hst[1].m, pInt2[0]);

    free(pInt1);
    free(pInt2);

    return 0;
}

К кодам будет идти предупреждение об «Обнаружена ошибка API Cuda: cudaMemcpy вернул (0xb)»

Я видел похожий вопрос: Копировать данные, которые размещены в устройстве с устройства на хост Но, похоже, не может решить мою проблему.

Thx.

1 Ответ

0 голосов
/ 13 сентября 2018

Хорошо, я работаю глупо (-.- !!).

При возврате из функции ядра я подсчитываю, сколько места мне нужно разместить в Host и Device, и снова cudaMalloc занимает большое место. Затем в другой функции ядра с именем ythread скопируйте данные из Heap в большое пространство.

typedef struct { int n, m; int *a; } myst;
__global__ void xthread(myst *st) {
    unsigned int idx = blockIdx.x * blockDim.x + threadIdx.x;
    myst *mst = &st[idx];
    mst->n = idx;
    mst->m = idx + 1;
    mst->a = (int *) malloc((mst->m) * sizeof(int));
    for (int i = 0; i < mst->m; i++) {
        mst->a[i] = idx + 900 + i * 10;
    }
}
__global__ void ythread(myst *st, int *total_a) {
    unsigned int idx = blockIdx.x*blockDim.x + threadIdx.x;
    myst *mst = &st[idx];
    int offset=0;
    for(int i=0; i<idx; i++) {
        offset += st[i].m;
    }
    for(int i=0; i<mst->m; i++) {
        total_a[offset+i] = mst->a[i];
    }
}
int main(int argc,char **argv) {
    dim3 dimGrid(1);
    dim3 dimBlock(2);
    myst *mst = NULL;
    cudaMalloc((void**)&mst, dimBlock.x * sizeof(myst));

    xthread<<<dimGrid, dimBlock>>>(mst);
    cudaDeviceSynchronize();

    myst *hst = (myst *)malloc(dimBlock.x * sizeof(myst));
    cudaMemcpy(hst, mst, dimBlock.x*sizeof(myst),cudaMemcpyDeviceToHost);

    int t_size = 0;
    for(int i=0; i<dimBlock.x; i++) {
        t_size += hst[i].m;
    }
    printf("t_size:%d\n", t_size);
    int * t_a_h = (int *)malloc(t_size*sizeof(int));
    int * t_a_d = NULL;
    cudaMalloc((void**)&t_a_d, t_size*sizeof(int));
    ythread<<<dimGrid, dimBlock>>>(mst, t_a_d);
    cudaDeviceSynchronize();
    cudaMemcpy(t_a_h, t_a_d, t_size*sizeof(int),cudaMemcpyDeviceToHost);

    for(int i=0; i<t_size; i++) {
        printf("t_a_h[%d]:%d\n", i, t_a_h[i]);
    }

    free(t_a_h);
    cudaFree(mst);
    cudaFree(t_a_d);

    return 0;
}

Эммммм, это работает, но я думаю, что есть лучший способ решить эту проблему.

...