2

我无法在主机上取消分配已在设备上分配的内存,也无法在设备上取消分配在主机上分配的内存。我将 CUDA 5.5 与 VS2012 和 Nsight 一起使用。是因为主机上的堆没有转移到设备上的堆还是相反,所以主机和设备之间的动态分配是未知的?

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

这是我的问题的一个例子:

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

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

2 回答 2

4

不,你不能这样做。

此主题在此处的编程指南中专门介绍

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

它在编程指南的第 B.18.2 节中,在第 B.18 节“B.18。动态全局内存分配和操作”中。

其基本原因是用于使用运行时(例如 )保留分配的机制cudaMalloccudaFree设备代码分配器是分开的,实际上它们在全局内存的逻辑独立区域之外保留。

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

于 2013-08-23T21:25:52.153 回答
0

这是我在主机上使用 CRT、主机的 CUDA API 和内核内存函数混合动态内存分配的解决方案。首先,如上所述,它们都必须使用不需要在没有事先通信和协调的情况下在系统和设备之间直接传输动态分配的策略来单独管理。如罗伯特的回答/评论中所述,需要手动数据副本,但不会针对内核的设备堆进行验证。

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

对于深度动态结构副本,在系统、主机和设备视角之间动态分配、管理和审核内存的过程很复杂。这是一个有效的策略,欢迎提出建议:

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

  2. 从主机为结构分配设备内存,并将结构复制到设备(即cudaMalloccudaMemcpy等);

  3. 在内核中,使用malloc创建使用设备堆管理的内存分配,并将指针保存在步骤 2 中设备上存在的结构中;

  4. 通过交换结构中每个指针的分配大小,将内核分配给系统的内容传达给系统;

  5. 主机使用系统中的 CUDA API(即 cudaMalloc)在设备上执行与内核在设备上所做的相同的分配,建议在结构中为此使用单独的指针变量;

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

  7. 内核清理内存分配;和,

  8. 主机使用cudaMemcpy将结构从设备中移动,上述答案评论中概述的类似策略可以根据需要用于深拷贝。

请注意,cudaHostMalloc和 system: malloc(或cudaHostMalloc)都共享相同的系统堆,使系统堆主机堆相同且可互操作,如上文引用的 CUDA 指南中所述。所以这里只提到系统堆设备堆。

于 2013-09-10T16:47:15.360 回答