gpt4 book ai didi

c - 动态结构数组的 GPU 内存分配

转载 作者:行者123 更新时间:2023-12-03 23:31:45 25 4
gpt4 key购买 nike

我在将结构数组传递给 gpu 内核时遇到问题。我基于这个话题 - cudaMemcpy segmentation fault我是这样写的:

#include <stdio.h>
#include <stdlib.h>

struct Test {
char *array;
};

__global__ void kernel(Test *dev_test) {
for(int i=0; i < 5; i++) {
printf("Kernel[0][i]: %c \n", dev_test[0].array[i]);
}
}

int main(void) {

int n = 4, size = 5;
Test *dev_test, *test;

test = (Test*)malloc(sizeof(Test)*n);
for(int i = 0; i < n; i++)
test[i].array = (char*)malloc(size * sizeof(char));

for(int i=0; i < n; i++) {
char temp[] = { 'a', 'b', 'c', 'd' , 'e' };
memcpy(test[i].array, temp, size * sizeof(char));
}

cudaMalloc((void**)&dev_test, n * sizeof(Test));
cudaMemcpy(dev_test, test, n * sizeof(Test), cudaMemcpyHostToDevice);
for(int i=0; i < n; i++) {
cudaMalloc((void**)&(test[i].array), size * sizeof(char));
cudaMemcpy(&(dev_test[i].array), &(test[i].array), size * sizeof(char), cudaMemcpyHostToDevice);
}

kernel<<<1, 1>>>(dev_test);
cudaDeviceSynchronize();

// memory free
return 0;
}

没有错误,但内核中显示的值不正确。我做错了什么?在此先感谢您的帮助。

最佳答案

  • 这是分配一个新的指向主机内存的指针:
     test[i].array = (char*)malloc(size * sizeof(char));
  • 这是将数据复制到主机内存中的该区域:
     memcpy(test[i].array, temp, size * sizeof(char));
  • 这是用指向设备内存的新指针覆盖先前分配的指向主机内存的指针(来自上面的步骤 1):
     cudaMalloc((void**)&(test[i].array), size * sizeof(char));

  • 在第 3 步之后,您在第 2 步中设置的数据将完全丢失,并且无法再以任何方式访问。引用 question/answer 中的第 3 步和第 4 步你链接:

    3.Create a separate int pointer on the host, let's call it myhostptr

    4.cudaMalloc int storage on the device for myhostptr


    你没有这样做。您没有创建单独的指针。您重用(删除、覆盖)现有指针,该指针指向您在主机上关心的数据。 This question/answer ,也从您链接的答案链接,在代码中几乎准确地提供了您需要遵循的步骤。
    这是您的代码的修改版本,它根据您链接的问题/答案正确实现了您未正确实现的缺失步骤 3 和 4(和 5):(请参阅描述步骤 3、4、5 的评论)
    $ cat t755.cu
    #include <stdio.h>
    #include <stdlib.h>

    struct Test {
    char *array;
    };

    __global__ void kernel(Test *dev_test) {
    for(int i=0; i < 5; i++) {
    printf("Kernel[0][i]: %c \n", dev_test[0].array[i]);
    }
    }

    int main(void) {

    int n = 4, size = 5;
    Test *dev_test, *test;

    test = (Test*)malloc(sizeof(Test)*n);
    for(int i = 0; i < n; i++)
    test[i].array = (char*)malloc(size * sizeof(char));

    for(int i=0; i < n; i++) {
    char temp[] = { 'a', 'b', 'c', 'd' , 'e' };
    memcpy(test[i].array, temp, size * sizeof(char));
    }

    cudaMalloc((void**)&dev_test, n * sizeof(Test));
    cudaMemcpy(dev_test, test, n * sizeof(Test), cudaMemcpyHostToDevice);

    // Step 3:
    char *temp_data[n];
    // Step 4:
    for (int i=0; i < n; i++)
    cudaMalloc(&(temp_data[i]), size*sizeof(char));
    // Step 5:
    for (int i=0; i < n; i++)
    cudaMemcpy(&(dev_test[i].array), &(temp_data[i]), sizeof(char *), cudaMemcpyHostToDevice);
    // now copy the embedded data:
    for (int i=0; i < n; i++)
    cudaMemcpy(temp_data[i], test[i].array, size*sizeof(char), cudaMemcpyHostToDevice);

    kernel<<<1, 1>>>(dev_test);
    cudaDeviceSynchronize();

    // memory free
    return 0;
    }

    $ nvcc -o t755 t755.cu
    $ cuda-memcheck ./t755
    ========= CUDA-MEMCHECK
    Kernel[0][i]: a
    Kernel[0][i]: b
    Kernel[0][i]: c
    Kernel[0][i]: d
    Kernel[0][i]: e
    ========= ERROR SUMMARY: 0 errors
    $
    由于上述方法对初学者来说可能具有挑战性,因此通常的建议不是这样做,而是扁平化您的数据结构。扁平化一般是指重新排列数据存储,以去除必须单独分配的嵌入指针。
    扁平化此数据结构的一个简单示例是使用它:
    struct Test {
    char array[5];
    };
    当然,人们认识到这种特定方法不会满足所有目的,但它应该说明一般的想法/意图。作为一个例子,通过这种修改,代码变得更加简单:
    $ cat t755.cu
    #include <stdio.h>
    #include <stdlib.h>

    struct Test {
    char array[5];
    };

    __global__ void kernel(Test *dev_test) {
    for(int i=0; i < 5; i++) {
    printf("Kernel[0][i]: %c \n", dev_test[0].array[i]);
    }
    }

    int main(void) {

    int n = 4, size = 5;
    Test *dev_test, *test;

    test = (Test*)malloc(sizeof(Test)*n);

    for(int i=0; i < n; i++) {
    char temp[] = { 'a', 'b', 'c', 'd' , 'e' };
    memcpy(test[i].array, temp, size * sizeof(char));
    }

    cudaMalloc((void**)&dev_test, n * sizeof(Test));
    cudaMemcpy(dev_test, test, n * sizeof(Test), cudaMemcpyHostToDevice);

    kernel<<<1, 1>>>(dev_test);
    cudaDeviceSynchronize();

    // memory free
    return 0;
    }
    $ nvcc -o t755 t755.cu
    $ cuda-memcheck ./t755
    ========= CUDA-MEMCHECK
    Kernel[0][i]: a
    Kernel[0][i]: b
    Kernel[0][i]: c
    Kernel[0][i]: d
    Kernel[0][i]: e
    ========= ERROR SUMMARY: 0 errors
    $

    关于c - 动态结构数组的 GPU 内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30082991/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com