2011-08-22 78 views
0

语境: CUDA 4.0,Linux的64位,NVIDIA UNIX x86_64的内核模块270.41.19,在的GeForce GTX 480CUDA内核代码的设备内存:是否明确可管理?

我试图找到我的程序(设备)内存泄漏。我使用运行时API和cudaGetMemInfo(free,total)来测量设备内存使用情况。内核执行后我注意到了一个重大的损失(在这种情况下是31M)。内核代码本身不分配任何设备内存。所以我猜想它是保留在设备内存中的内核代码。即使我会认为内核不是那么大。 (有没有确定内核大小的方法?)

何时将内核代码加载到设备内存中?我想执行主机代码行:

kernel<<<geom>>>(params); 

对不对? 在调用之后代码是否保留在设备内存中?如果是这样,我可以明确卸载代码吗?

我担心的是设备内存碎片。考虑交替设备内存分配和内核执行的大量序列(不同的内核)。过了一段时间后,设备内存变得非常稀少。即使你释放了一些内存,内核代码仍然只留下内核之间的空间用于新分配。这会在一段时间后导致巨大的内存碎片。这是CUDA的设计方式吗?

+0

你在使用任何全局内存吗?全局内存将保持分配状态,直到您关闭设备或释放它为止(如果它是cudamalloc'ed) – asm

+0

内核被定义为“__global__”,但没有别的。 – ritter

+0

这里的全局并不意味着'__global__'关键字,它只是意味着在你的.cu文件或通过cudamalloc分配的任何内存中在全局范围内声明的任何内容。因此,例如,如果在.cu文件的全局范围内有'int8 [1024]',或者如果您在没有匹配的cudaFree的情况下调用'cudaMalloc(8 * 1024)',您将拥有突出的1KB内存占用空间。 – asm

回答

2

您正在观察的内存分配由CUDA上下文使用。它不仅包含内核代码,还包含本地存储器的任何其他静态作用域设备符号,纹理,每线程暂存空间,printf和堆,常量内存以及驱动程序和CUDA运行时本身所需的gpu内存。大多数内存只能分配一次,当加载一个二进制模块时,或者驱动程序编译的PTX代码是JIT。最好把它看作是一个固定的开销,而不是泄漏。 PTX代码中有200万条指令限制,当前硬件使用32位字指令,所以即使是最大允许内核代码的内存占用量与其所需的其他全局内存开销相比也较小。

在最新版本的CUDA中,有一个运行时API调用cudaDeviceSetLimit,它允许对给定上下文消耗的暂存空间量进行一些控制。请注意,可以将限制设置为低于设备代码要求的值,在这种情况下,可能会导致运行时执行失败。

+0

感谢您的回答!你知道内核代码是否保留在内存空间中,直到上下文重置?还是它像内核代码的缓存?如果一个程序拥有大量不同的内核,它们是否都留在内存中呢? – ritter

+0

没有记录。将模块加载到上下文中时,将加载所有外部可见符号和体系结构兼容二进制有效内容。但是,他们是否在加载时直接进入设备是我不知道的。 – talonmies