使用CudaMalloc分配的设备内存是否在设备上无法访问?

时间:2013-08-23 21:20:05

标签: memory dynamic cuda

我无法在我在设备上分配的主机上释放内存,或者在我在主机上分配的设备上释放内存。我使用带有VS2012和Nsight的CUDA 5.5。是因为主机上的堆没有转移到设备上的堆上,反之亦然,因此主机和设备之间的动态分配是未知的?

如果这是在文档中,则不容易找到。同样重要的是要注意,在我使用CUDA调试并启用了Memory Checker运行程序之前,不会抛出错误。该问题并未导致CUDA调试之外的崩溃,但如果我没有追溯检查内存问题,则会导致问题。如果有一种方便的方法将堆/堆栈从主机复制到设备,那就太棒了......希望和梦想。

以下是我的问题的一个例子:

__global__ void kernel(char *ptr)
{
  free(ptr);
}

void main(void)
{
  char *ptr;
  cudaMalloc((void **)&ptr, sizeof(char *), cudaMemcpyHostToDevice);
  kernel<<<1, 1>>>(ptr);
}

2 个答案:

答案 0 :(得分:4)

不,你不能这样做。

编程指南here

中特别介绍了此主题
  

通过malloc()分配的内存不能使用运行时释放(即,通过调用设备内存中的任何空闲内存函数)。   类似地,通过运行时分配的内存(即通过调用设备内存中的任何内存分配函数)不能通过free()释放。

在节目指南的B.18.2节中,在B.18节“B.18。动态全局存储器分配和操作”中。

它的基本原因是用于使用运行时保留分配的机制(例如cudaMalloccudaFree)与设备代码分配器是分开的,实际上它们保留了逻辑上的单独分离全球记忆的区域。

您可能需要阅读编程指南的整个B.18部分,其中包含有关设备动态内存分配的这些主题。

答案 1 :(得分:0)

这是我使用CRT在主机上混合动态内存分配,主机的CUDA API以及内核内存功能的解决方案。首先,如上所述,它们都必须使用不需要动态分配的策略单独管理,无需事先通信和协调就可以在系统和设备之间直接传输。如Robert的回答/评论所述,手动数据副本是不需要对内核的设备堆进行验证的。

我还建议跟踪 audit ,在3种不同的内存管理API中分配和解除分配的字节数。例如,每次调用系统:malloc,host:cudaMalloc,device:malloc或关联的frees时,使用变量来保存每个堆中分配或解除分配的字节数,即来自系统,主机,设备。这有助于在调试时跟踪泄漏。

  

动态分配,管理和审核的过程非常复杂   系统,主机和设备之间的内存深层次   动态结构副本。这是一个有效的策略,建议   欢迎:

     
      
  1. 使用 cudaHostMalloc malloc 分配系统内存   结构类型,包含系统堆上的指针;

  2.   
  3. 从主机为结构分配设备内存,然后复制   设备的结构(即 cudaMalloc cudaMemcpy 等);

  4.   
  5. 在内核中,使用 malloc 创建内存分配   使用设备堆进行管理并将指针保存在   从步骤2开始存在于设备上的结构;

  6.   
  7. 通过交换将内核分配给系统的内容进行通信   结构中每个指针的分配大小;

  8.   
  9. 主机使用CUDA API在设备上执行相同的分配(即   来自系统的 cudaMalloc )就像设备上的内核所做的那样,   建议在结构中有一个单独的指针变量   这;

  10.   
  11. 此时,从内核动态分配的内存   设备内存可以动态手动复制到该位置   主机在设备内存中分配(即不使用主机: memcpy ,   设备: memcpy cudaMemcpy );

  12.   
  13. 内核清理内存分配;和,

  14.   
  15. 主持人使用 cudaMemcpy 从设备移动结构,   可以使用上述答案中概述的类似策略   如深拷贝所需。

  16.   

注意, cudaHostMalloc 和系统: malloc (或 cudaHostMalloc )都共享相同的系统堆,使系统堆主机堆相同且可互操作,如上面引用的CUDA指南中所述。因此,仅提及系统堆设备堆