Linux 增加虚拟内存而不增加虚拟机大小
我在谷歌和这个网站上搜索了我的问题,但我仍然不明白解决方案 我有一个Linux 增加虚拟内存而不增加虚拟机大小,linux,fortran,mpi,Linux,Fortran,Mpi,我在谷歌和这个网站上搜索了我的问题,但我仍然不明白解决方案 我有一个MPI程序,它RECV一些数据。程序在大数组中崩溃,错误内存不足,因此我开始考虑 /PRO/SUB/STATION/COD>文件。 在MPI_RECV之前,它是: Name: model.exe VmPeak: 841640 kB VmSize: 841640 kB VmHWM: 15
MPI
程序,它RECV
一些数据。程序在大数组中崩溃,错误内存不足,因此我开始考虑<代码> /PRO/SUB/STATION/COD>文件。
在MPI_RECV之前,它是:
Name: model.exe
VmPeak: 841640 kB
VmSize: 841640 kB
VmHWM: 15100 kB
VmRSS: 15100 kB
VmData: 760692 kB
及之后:
Name: model.exe
VmPeak: 841640 kB
VmSize: 841640 kB
VmHWM: 719980 kB
VmRSS: 719980 kB
VmData: 760692 kB
我在Ubuntu上测试它,通过系统监视器我看到内存在增加。但我感到困惑的是,VmSize
(和VmPeak
)参数没有变化
问题是——实际内存使用的指标是什么
这是否意味着,真正的指标是VmRSS
?(并且VmSize
只分配了内存,但仍然没有使用内存)(您的问题的可能解决方案是最后一段)
在大多数具有虚拟内存的现代操作系统上,内存分配是一个两阶段的过程。首先,保留进程的一部分虚拟地址空间,并且进程的虚拟内存大小(VmSize
)相应增加。这将在所谓的流程页面表中创建条目。页面最初与物理内存帧没有关联,即没有实际使用物理内存。每当实际读取或写入此分配部分的某些部分时,就会发生页面错误,操作系统会从物理内存安装(映射)一个空闲页面。这会增加进程的常驻集大小(VmRSS
)。当一些其他进程需要内存时,操作系统可能会将一些不常使用的页面(不常使用的页面的定义高度依赖于实现)的内容存储到一些持久性存储(大多数情况下是硬盘驱动器,或者通常是交换设备),然后取消映射。此过程会减少RSS,但保持VmSize
不变。如果以后访问此页面,将再次出现页面错误并将其恢复。虚拟内存大小仅在释放虚拟内存分配时减小。请注意,VmSize
还计算内存映射文件(即可执行文件及其链接到的所有共享库或其他显式映射文件)和共享内存块
进程中有两种通用的内存类型—静态分配内存和堆内存。静态分配的内存保留所有常量和全局/静态变量。它是数据段的一部分,其大小由VmData
度量表示。数据段还承载程序堆的一部分,在那里分配动态内存。数据段是连续的,也就是说,它从某个位置开始,向堆栈方向向上增长(堆栈从非常高的地址开始,然后向下增长)。数据段中的堆的问题在于,它由一个特殊的堆分配器管理,该分配器负责将连续数据段细分为更小的内存块。另一方面,在Linux中,还可以通过直接映射虚拟内存来分配动态内存。为了节省内存,通常只对较大的分配执行此操作,因为它只允许分配页面大小的倍数(通常为4kib)的内存
堆栈也是大量内存使用的一个重要来源,特别是在自动(堆栈)存储中分配大阵列时。堆栈从可用虚拟地址空间的最顶端开始,向下增长。在某些情况下,它可能到达数据段的顶部,或者可能到达其他虚拟分配的末端。坏事情就会发生。堆栈大小在VmStack
度量和VmSize
度量中计算。
可以这样概括:
负责所有虚拟内存分配(文件映射、共享内存、堆内存、任何内存),并且几乎每次分配新内存时都会增长。几乎是这样,因为如果新的堆内存分配是在数据段中取代已释放的旧分配,则不会分配新的虚拟内存。每当释放虚拟分配时,它都会递减VmSize
跟踪VmPeak
的最大值-它只能随时间增加VmSize
随着内存被访问而增加,随着内存被调出到交换设备而减少VmRSS
随着堆的数据段部分的使用而增长。它几乎从不收缩,因为当前堆分配器保留释放的内存,以备将来的分配需要VmData
VmLck
)。这是不允许分页的内存。它如何增长和收缩取决于MPI实现。有些人从不注销已经注册的块(关于为什么这么做的技术细节太复杂,这里无法描述),其他人这样做是为了更好地使用虚拟内存管理器
在您的情况下,您会说您遇到了虚拟内存大小限制。这可能意味着此限制设置得太低,或者您正在运行操作系统强加的限制。首先,Linux(和大多数Unix)有办法通过ulimit
机制施加人为限制。在shell中运行ulimit-v
将告诉您虚拟内存大小的限制是多少(以KiB为单位)。您可以使用ulimit-v
设置限制。这只适用于当前shell生成的进程及其子进程grandchilren等。如果要在远程节点上启动所有其他进程,则需要指示mpiexec
(或mpirun
)将此值传播到所有其他进程。如果您是在一些工作负载管理器(如LSF、Sun/Oracle网格引擎、Torque/PBS等)的控制下运行程序,那么有一些作业参数