【问题标题】:How to copy the memory allocated in device function back to main memory如何将设备功能中分配的内存复制回主内存
【发布时间】:2012-10-14 03:15:44
【问题描述】:

我有一个 CUDA 程序,其中包含一个主机函数和一个设备函数Execute()。在主机函数中,我分配了一个全局内存输出,然后将其传递给设备函数并用于存储设备函数中分配的全局内存的地址。我想访问主机函数中内核分配的内存。以下是代码:

#include <stdio.h>
typedef struct                      
{
  int             * p;            
  int              num;            
} Structure_A;

__global__ void Execute(Structure_A *output);

int main(){

    Structure_A *output;
    cudaMalloc((void***)&output,sizeof(Structure_A)*1);
    dim3 dimBlockExecute(1,1);
    dim3 dimGridExecute(1,1);
    Execute<<<dimGridExecute,dimBlockExecute>>>(output);
    Structure_A * output_cpu;
    int * p_cpu;
    cudaError_t err;

    output_cpu= (Structure_A*)malloc(sizeof(Structure_A));
    err=cudaMemcpy(output_cpu,output,sizeof(Structure_A),cudaMemcpyDeviceToHost);    
    if( err != cudaSuccess)
    {
        printf("CUDA error a: %s\n", cudaGetErrorString(err));
        exit(-1);
    }
    p_cpu=(int *)malloc(sizeof(int));
    err=cudaMemcpy(p_cpu,output_cpu[0].p,sizeof(int),cudaMemcpyDeviceToHost);    
    if( err != cudaSuccess)
    {
        printf("CUDA error b: %s\n", cudaGetErrorString(err));
        exit(-1);
    }   
    printf("output=(%d,%d)\n",output_cpu[0].num,p_cpu[0]);
    return 0;
}

__global__ void Execute(Structure_A *output){

    int thid=threadIdx.x;

    output[thid].p= (int*)malloc(thid+1);

    output[thid].num=(thid+1);

    output[thid].p[0]=5;
} 

我可以编译程序。但是当我运行它时,我得到一个错误,表明以下内存复制函数中存在无效参数:

err=cudaMemcpy(p_cpu,output_cpu[0].p,sizeof(int),cudaMemcpyDeviceToHost); 

CUDA 版本是 4.2。 CUDA卡:特斯拉C2075 操作系统:x86_64 GNU/Linux

编辑:修改代码并为 output_cpu 和 p_cpu 分配适当大小的内存。

【问题讨论】:

    标签: cuda


    【解决方案1】:

    这段代码有很多问题。例如,您只在这两行中分配 1 个字节,不足以容纳 Structure_A 的单个实例。

    output_cpu= (Structure_A*)malloc(1);
    p_cpu=(int *)malloc(1);
    

    但您的错误的直接原因是您正在从设备运行时堆分配的指针(即在您的设备代码中分配 mallocnew)到主机指针执行 memcpy。

    err=cudaMemcpy(p_cpu,output_cpu[0].p,sizeof(int),cudaMemcpyDeviceToHost);   
    

    很遗憾,cudaMalloc、cudaFree 和 cudaMemcpy 的主机运行时 API 目前与设备运行时堆上分配的内存不兼容。

    【讨论】:

    • 您的最后一个指针不正确。 output_cpu[0].p 是设备指针,但它是在运行时堆上分配的,因此不支持 API 设备到主机的传输。
    • 谢谢,对我来说,OP 在设备上调用 malloc/new 对我来说并不明显,因为 OP 不包含任何内核代码。应该更仔细地阅读。我已经编辑了 OP 的代码以明确这一点。
    • 感谢您的评论。我认为既然我们可以有一个设备指针来存储使用 cudaMalloc 函数分配的全局内存的地址,并使用 cudaMemcpy 函数将该全局内存中的值复制回主内存,我们应该能够做同样的事情在运行时堆上分配的全局内存。
    • 现在我了解到在运行时堆上分配的全局内存无法复制回主内存。但是分配我们无法从主机函数访问的内存有什么意义呢?
    • @xhe8:关键是您可以从设备访问它。编写初始化内核以在 GPU 内存中设置和填充复杂结构,然后在 GPU 中处理它们,最后将结果“展平”以传输回主机通常比尝试使用托管 API 来执行相同的任务。
    猜你喜欢
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多