CUDA中的持久缓冲区

CUDA中的持久缓冲区,cuda,Cuda,我有一个应用程序,我需要分配和维护一个持久缓冲区,该缓冲区可由CUDA中连续启动的多个内核使用。我最终需要将这个缓冲区的内容复制回主机 我的想法是声明一个全局范围设备符号,它可以直接在不同的内核中使用,而无需作为显式内核参数传递,比如 __device__ char* buffer; 但是,我不确定应该如何分配内存并将地址分配给这个设备指针,以便内存具有我需要的持久作用域。所以我的问题实际上分为两部分: 分配全局内存的各种方法的生存期是多少 如何分配内存并为全局范围指针赋值?是否有必要使用设备

我有一个应用程序,我需要分配和维护一个持久缓冲区,该缓冲区可由CUDA中连续启动的多个内核使用。我最终需要将这个缓冲区的内容复制回主机

我的想法是声明一个全局范围设备符号,它可以直接在不同的内核中使用,而无需作为显式内核参数传递,比如

__device__ char* buffer;
但是,我不确定应该如何分配内存并将地址分配给这个设备指针,以便内存具有我需要的持久作用域。所以我的问题实际上分为两部分:

  • 分配全局内存的各种方法的生存期是多少
  • 如何分配内存并为全局范围指针赋值?是否有必要使用设备代码
    malloc
    并运行一个安装内核来实现这一点,或者我可以使用主机端API的一些组合来实现这一点
  • [后记:此问题已作为问答发布,以回应类似主题的提问]

    分配全局内存的各种方法的生存期是多少

    所有全局内存分配都有其分配上下文的生存期。这意味着您的应用程序分配的任何全局内存根据您的定义都是“持久的”,无论您是在GPU运行时堆上使用主机端API还是设备端分配

    如何分配内存并为全局作用域赋值 指针?是否需要使用设备代码
    malloc
    并运行安装程序 内核,或者我可以使用一些主机端API的组合来 实现这一目标

    这两种方法都可以根据需要工作,尽管主机API的使用要简单得多。这两种方法之间也有一些重要的区别

    在设备代码中使用
    malloc
    new
    的内存分配在设备运行时堆上分配。在设备代码中运行
    malloc
    之前,必须使用适当大小的堆,否则调用可能会失败。而且主机端内存管理API无法访问设备堆,因此您还需要一个复制内核将内存内容传输到主机API可访问内存,然后才能将内容传输回主机

    另一方面,主机API案例非常简单,没有设备端
    malloc
    的限制。一个简单的例子如下所示:

    __device__ char* buffer;
    
    int main()  
    {
        char* d_buffer;
        const size_t buffer_sz = 800 * 600 * sizeof(char);
    
        // Allocate memory
        cudaMalloc(&d_buffer, buffer_sz);
    
        // Zero memory and assign to global device symbol
        cudaMemset(d_buffer, 0, buffer_sz);
        cudaMemcpyToSymbol(buffer, &d_buffer, sizeof(char*));
    
        // Kernels go here using buffer
    
        // copy to host
        std::vector<char> results(800*600);
        cudaMemcpy(&results[0], d_buffer, buffer_sz, cudaMemcpyDeviceToHost);
    
        // buffer has lifespan until free'd here
        cudaFree(d_buffer);
    
        return 0;
      };
    
    \uuuu设备\uuuuu字符*缓冲区;
    int main()
    {
    char*d_缓冲区;
    常量大小缓冲区大小=800*600*sizeof(字符);
    //分配内存
    Cudamaloc(d_缓冲区和d_sz缓冲区);
    //零内存并分配给全局设备符号
    cudaMemset(d_缓冲区,0,缓冲区_sz);
    cudaMemcpyToSymbol(buffer,&d_buffer,sizeof(char*));
    //内核在这里使用缓冲区
    //复制到主机
    标准:向量结果(800*600);
    cudaMemcpy(&results[0],d_buffer,buffer_sz,cudamemcpydevicetoost);
    //缓冲区在这里释放之前有使用寿命
    cudaFree(d_缓冲区);
    返回0;
    };
    
    [标准免责声明:在浏览器中编写的代码,未经编译或测试,使用风险自负]

    因此,基本上您可以使用标准的主机端API实现您想要的功能:
    cudamaloc
    cudaMemcpyToSymbol
    cudaMemcpy
    。不需要其他任何东西

    分配全局内存的各种方法的生存期是多少

    所有全局内存分配都有其分配上下文的生存期。这意味着您的应用程序分配的任何全局内存根据您的定义都是“持久的”,无论您是在GPU运行时堆上使用主机端API还是设备端分配

    如何分配内存并为全局作用域赋值 指针?是否需要使用设备代码
    malloc
    并运行安装程序 内核,或者我可以使用一些主机端API的组合来 实现这一目标

    这两种方法都可以根据需要工作,尽管主机API的使用要简单得多。这两种方法之间也有一些重要的区别

    在设备代码中使用
    malloc
    new
    的内存分配在设备运行时堆上分配。在设备代码中运行
    malloc
    之前,必须使用适当大小的堆,否则调用可能会失败。而且主机端内存管理API无法访问设备堆,因此您还需要一个复制内核将内存内容传输到主机API可访问内存,然后才能将内容传输回主机

    另一方面,主机API案例非常简单,没有设备端
    malloc
    的限制。一个简单的例子如下所示:

    __device__ char* buffer;
    
    int main()  
    {
        char* d_buffer;
        const size_t buffer_sz = 800 * 600 * sizeof(char);
    
        // Allocate memory
        cudaMalloc(&d_buffer, buffer_sz);
    
        // Zero memory and assign to global device symbol
        cudaMemset(d_buffer, 0, buffer_sz);
        cudaMemcpyToSymbol(buffer, &d_buffer, sizeof(char*));
    
        // Kernels go here using buffer
    
        // copy to host
        std::vector<char> results(800*600);
        cudaMemcpy(&results[0], d_buffer, buffer_sz, cudaMemcpyDeviceToHost);
    
        // buffer has lifespan until free'd here
        cudaFree(d_buffer);
    
        return 0;
      };
    
    \uuuu设备\uuuuu字符*缓冲区;
    int main()
    {
    char*d_缓冲区;
    常量大小缓冲区大小=800*600*sizeof(字符);
    //分配内存
    Cudamaloc(d_缓冲区和d_sz缓冲区);
    //零内存并分配给全局设备符号
    cudaMemset(d_缓冲区,0,缓冲区_sz);
    cudaMemcpyToSymbol(buffer,&d_buffer,sizeof(char*));
    //内核在这里使用缓冲区
    //复制到主机
    标准:向量结果(800*600);
    cudaMemcpy(&results[0],d_buffer,buffer_sz,cudamemcpydevicetoost);
    //缓冲区在这里释放之前有使用寿命
    cudaFree(d_缓冲区);
    返回0;
    };
    
    [标准免责声明:在浏览器中编写的代码,未经编译或测试,使用风险自负]

    因此,基本上您可以使用标准的主机端API实现您想要的功能:
    cudamaloc
    cudaMemcpyToSymbol
    cudaMemcpy
    。不需要其他任何东西