2012-07-24 91 views
11

我正在分析我的Cuda 4程序,结果发现在某个阶段运行的进程使用了​​超过80 GiB的虚拟内存。这比我预期的要多得多。 检查存储器映射随着时间的演变,并比较其正在执行什么样的代码行后,它原来,这些简单的指令的虚拟内存使用颠簸到80吉布之后:为什么Cuda运行时会在初始化时保留80 GiB虚拟内存?

int deviceCount; 
    cudaGetDeviceCount(&deviceCount); 
    if (deviceCount == 0) { 
    perror("No devices supporting CUDA"); 
    } 

显然,这是第一次Cuda调用,因此运行时被初始化。在此之后,内存映射看上去像(部分):

Address   Kbytes  RSS Dirty Mode Mapping 
0000000000400000 89796 14716  0 r-x-- prg 
0000000005db1000  12  12  8 rw--- prg 
0000000005db4000  80  76  76 rw--- [ anon ] 
0000000007343000 39192 37492 37492 rw--- [ anon ] 
0000000200000000 4608  0  0 ----- [ anon ] 
0000000200480000 1536 1536 1536 rw--- [ anon ] 
0000000200600000 83879936  0  0 ----- [ anon ] 

现在有了映射到虚拟内存空间,这个巨大的存储区。

好吧,它可能不是一个大问题,因为在Linux中预留/分配内存的操作并不多,除非您实际写入此内存。但它真的很烦人,因为例如MPI作业必须用作业可用的最大vmem来指定。而80GiB对于Cuda工作来说只是一个较低的边界 - 我们也必须添加所有其他的东西。

我可以想象它与Cuda保持的所谓暂存空间有关。内核代码的一种内存池,可以动态增长和缩小。但这是猜测。它也分配在设备内存中。

任何见解?

回答

12

与暂存空间无关,它是寻址系统的结果,它允许主机和多个GPU之间的统一处理和对等访问。 CUDA驱动程序使用内核的虚拟内存系统将所有GPU内存+主机内存注册到单个虚拟地址空间中。它本质上并不是内存消耗,它只是将所有可用地址空间映射到线性虚拟空间以进行统一寻址的“技巧”。

+0

好的,有道理。所以,在我的情况下,主机安装了48 GB RAM + 8 GB交换和4个GPU,每个6 GB共80 GB。答对了!这是否意味着如果我在正常的堆上分配,这也会出现在这些80GB内? – ritter 2012-07-24 13:43:40

+0

堆只是每个GPU上每个上下文的内存分配。由于堆不会在虚拟内存中发生更改,但给定GPU上的API报告的可用内存将减少。 – talonmies 2012-07-24 14:03:46

+7

@Frank:我可以有你的电脑吗? :) – 2012-07-24 16:39:37