我无法在我在设备上分配的主机上释放内存,或者在我在主机上分配的设备上释放内存。我使用带有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);
}
答案 0 :(得分:4)
不,你不能这样做。
编程指南here
中特别介绍了此主题通过malloc()分配的内存不能使用运行时释放(即,通过调用设备内存中的任何空闲内存函数)。 类似地,通过运行时分配的内存(即通过调用设备内存中的任何内存分配函数)不能通过free()释放。
在节目指南的B.18.2节中,在B.18节“B.18。动态全局存储器分配和操作”中。
它的基本原因是用于使用运行时保留分配的机制(例如cudaMalloc
,cudaFree
)与设备代码分配器是分开的,实际上它们保留了逻辑上的单独分离全球记忆的区域。
您可能需要阅读编程指南的整个B.18部分,其中包含有关设备动态内存分配的这些主题。
答案 1 :(得分:0)
这是我使用CRT在主机上混合动态内存分配,主机的CUDA API以及内核内存功能的解决方案。首先,如上所述,它们都必须使用不需要动态分配的策略单独管理,无需事先通信和协调就可以在系统和设备之间直接传输。如Robert的回答/评论所述,手动数据副本是不需要对内核的设备堆进行验证的。
我还建议跟踪 audit ,在3种不同的内存管理API中分配和解除分配的字节数。例如,每次调用系统:malloc,host:cudaMalloc,device:malloc或关联的frees时,使用变量来保存每个堆中分配或解除分配的字节数,即来自系统,主机,设备。这有助于在调试时跟踪泄漏。
动态分配,管理和审核的过程非常复杂 系统,主机和设备之间的内存深层次 动态结构副本。这是一个有效的策略,建议 欢迎:
使用 cudaHostMalloc 或 malloc 分配系统内存 结构类型,包含系统堆上的指针;
从主机为结构分配设备内存,然后复制 设备的结构(即 cudaMalloc , cudaMemcpy 等);
在内核中,使用 malloc 创建内存分配 使用设备堆进行管理并将指针保存在 从步骤2开始存在于设备上的结构;
通过交换将内核分配给系统的内容进行通信 结构中每个指针的分配大小;
主机使用CUDA API在设备上执行相同的分配(即 来自系统的 cudaMalloc )就像设备上的内核所做的那样, 建议在结构中有一个单独的指针变量 这;
此时,从内核动态分配的内存 设备内存可以动态手动复制到该位置 主机在设备内存中分配(即不使用主机: memcpy , 设备: memcpy 或 cudaMemcpy );
内核清理内存分配;和,
- 醇>
主持人使用 cudaMemcpy 从设备移动结构, 可以使用上述答案中概述的类似策略 如深拷贝所需。
注意, cudaHostMalloc 和系统: malloc (或 cudaHostMalloc )都共享相同的系统堆,使系统堆和主机堆相同且可互操作,如上面引用的CUDA指南中所述。因此,仅提及系统堆和设备堆。