杭州锐达数字技术有限公司
声振论坛 首页 科学计算 matlab 查看内容

Out of memory:Matlab数据处理常见问题总结

2018-7-11 16:44| 发布者: weixin| 查看: 19| 评论: 0|原作者: weixin|来自: 声振之家公众号

摘要: 本文介绍了Matlab数据处理常见问题总结
  Matlab中“Out of memory”问题总是相当令人头疼,比如大矩阵做运算时一不小心就会出现。其原因在于:内存在使用的过程中会不断的分配和释放,导致被分割成很多不连续的区域(操作系统知识)。而Matlab中矩阵的存储是以块(block)的形式存储的,也就是说当Matlab在为即将存储的矩阵划分block时,如果没有相应大小的连续内存用于分配,就会报告“Out of Memory”----即便实际内存没有被完全使用。

  遇到这个问题时,首先要学会使用help命令查看内存相关的命令及其用法(matlab最最最权威的指导材料,你值得拥有)。例如使用”memory“命令查看内存使用情况,举个例子:

  >>memory
  Maximum possible array: 1102 MB (1.155e+009 bytes) *
  #当前系统数组能占的最大内存
  Memory available for all arrays: 1427 MB (1.496e+009 bytes) **
  #当前系统变量可被分配的空间
  Memory used by MATLAB: 363 MB (3.811e+008 bytes)
  #matlab已经使用的内存数量
  Physical Memory (RAM): 3063 MB (3.212e+009 bytes)
  #系统物理内存数量
  * Limited by contiguous virtual address space available.
  #打星号表示受限于连续可用的虚拟地址空间(内存空间)
  ** Limited by virtual address space available.
  #打双星号表示受限于可用的虚拟地址空间(内存空间)

  (以上是以32位windows系统为例)

  此外,由于反复分配和释放内存会使可用的连续内存段减少,因此当 Matlab 刚刚启动时连续内存最多,此时往往可以新建非常大的数组,这一点可以用命令“feature('memstats')”(matlab version >= 7.0)看出。如果显示的最大连续内存段很小,但实际可用内存(非连续的)仍旧很多,则表明内存中碎片太多了。再举个例子:

  >> feature('memstats')
  Physical Memory (RAM):
  In Use: 2189 MB (88db8000)
  Free: 873 MB (36924000)
  Total: 3062 MB (bf6dc000)
  Page File (Swap space):
  In Use: 3239 MB (ca7be000)
  Free: 2884 MB (b4444000)
  Total: 6124 MB (17ec02000)
  Virtual Memory (Address Space):
  In Use: 612 MB (264d2000)
  Free: 1435 MB (59b0e000)
  #总的可用内存
  Total: 2047 MB (7ffe0000)
  Largest Contiguous Free Blocks:
  1. [at 24440000] 1101 MB (44d90000)
  2. [at 691dd000] 54 MB ( 36b3000)
  3. [at 784bc000] 39 MB ( 27e4000)
  4. [at 6de02000] 20 MB ( 14ee000)
  5. [at 6fe1b000] 17 MB ( 11e5000)
  6. [at 20330000] 16 MB ( 1080000)
  7. [at 7b31e000] 16 MB ( 1072000)
  8. [at 1e7b0000] 16 MB ( 1040000)
  9. [at 6f330000] 10 MB ( ae0000)
  10. [at 71fb4000] 9 MB ( 9dc000)
  ======= ==========
  1304 MB (518e8000)
  #实际可用的连续内存


  ans =
  1.1551e+009

  其次才是参考如下解决方案:

  系统操作类

  1、终极解决办法:升级为64位系统,然后增加内存!
  2、增加虚拟内存:如果不想升级系统,那就增加虚拟内存吧。

  附:不同的OS修改虚拟内存方法
  (1) UNIX
  Information about swap space can be procured by typing pstat -s at the UNIX command prompt. For detailed information on changing swap space, ask your system administrator.
  (2) Linux
  Swap space can be changed by using the mkswap and swapon commands. For more information on the above commands, type man followed by the command name at the Linux prompt.
  (3) Windows NT/2000/XP
  右键“我的电脑”->“属性”->“高级”->“性能”->“设置”->“高级”->“虚拟内存”,点击“更改”。
  (4) Windows Vista/7
  右键“计算机”->“属性”->“高级系统设置”->“性能”->“设置”->“高级”->“虚拟内存”,点击“更改”。

  3、打开3GB开关(Matlab version >= 7.0.1):某些windows系统中可以采用3GB 开关,使用3GB开关启动的系统中每个进程可以再多分配1GB的虚拟地址空间。

  方法之一是修改C盘根目录中的“boot.ini”文件,为启动选项加上 /3G 。例如:multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /3G。

  方法之二是右键“我的电脑”->“属性”->“高级”->“启动和故障修复”->“设置”->“编辑”->将最后一行语句复制,粘贴在下一行,并加上/3gb。例如:最后一行语句是multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional",则先复制,并粘贴在下一行,并将这行改为multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional with 3GB switche" /3gb 。最后点击”存储“->”确定“,并重启计算机,在开机显示操作系统时,选择带有 3GB switche的一项即可。

  但是只有如下系统才能使用3GB开关:
  • Microsoft Windows Server 2003 Enterprise Edition
  • Microsoft Windows Server 2003 Datacenter Edition
  • Microsoft Windows Small Business Server 2003
  • Microsoft Windows XP Professional
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Datacenter Server
  • Microsoft Windows NT 4.0 Enterprise Server
  关于3GB开关的详细说明请参考:关于windows XP 支持 4GB内存的问题

  4、尽量少使用Windows系统资源:Windows中字体、窗口等都是要占用系统资源的,所以在Matlab运行时尽量不要打开不用的窗口,最好的办法是只留一个Matlab在那里跑程序。

  Matlab环境操作类
  5、使用pack命令:前面说过,当内存被分为很多碎片以后,其实很有可能没有被用完并且存在很大的空余空间,只是没有足够的连续空间,即大的block而已。所以如果内存碎片过多时,或者在执行耗内存操作之前,使用pack命令整理一下内存能够起到一定作用:其作用就是将所有内存中的数组写入硬盘,然后重新建立这些数组,以减少内存碎片。

  注意:pack只能在command window中使用,不能用于脚本中,所以我常常采用的办法是让程序分段运行,前一段的变量先save起来,然后pack,然后在后一段程序中load进来继续运行,如此循环。

  6、关闭java虚拟机:如果必有必要,不要启动java虚拟机,采用matlab -nojvm启动 (在快捷方式属性里面的 "..../matlab.exe") 改为("...../matlab.exe" - nojvm)

  7、关闭Matlab Server
  附:与内存相关的Matlab命令参考:Memory Usage - MATLAB & Simulink - MathWorks 中国

  代码操作类:优化你的程序
  8、使用稀疏矩阵,或者将矩阵转化成稀疏形式(help sparse你懂的):稀疏形式的矩阵使用内存更少,执行时间更短,所以当矩阵中有大量的0的时候最好存储成稀疏形式。例如:1000*1000的矩阵M,其中2/3的元素为0,使用普通形式X与稀疏形式Y两种存储方法的比较如下:
1.png
  9、划分大矩阵:此外如果可行的话,将一个大的矩阵划分为几个小的矩阵分别操作,这样每一次使用的内存减少,降低报错的可能性。

  10、使用save和load:大的变量先用save保存,需要使用时再load进来。

  11、减少使用双精度浮点(double)类型,使用单精度浮点(single)或者短整数(uint8/uint16)替代:Matlab 默认的数字类型是双精度浮点数(double),每个双浮点数占用 8 个字节。对于一些整数操作来说,使用双浮点数显得很浪费,所以可以在预先分配数组时指定使用的数字类型,例如以下命令:zeros(10, 10, 'uint8') 。对于浮点数,在很多精度要求不高的情况下,可以使用4个字节的单精度浮点数(single),可以减少一半的内存。关于单、双浮点数的精度对照如下,根据需要选择使用:

  single:精度(1.1921e-007),最大数(3.4028e+038)
  double:精度(2.2204e-016),最大数(1.7977e+308)

  12、为矩阵变量预先分配内存而不是动态分配:在动态分配内存的过程中,由于开始Matlab所用的block会随着矩阵的增大而连续的为此矩阵分配内存,但是由于block的不连续性,很有可能最开始分配的block不能满足存储的需要,Matlab只好移动此block以找到更大的block来存储该矩阵,这样在移动的过程中不但占用了大量的时间,而且很有可能Matlab找不到更大的块来存储,从而导致“Out of Memory”。而当你为矩阵预先分配足够的内存时,Matlab会在开始运算前一次性找到最合适的block来存储矩阵,而不用计算过程中再寻找。比较两个程序:

  for i = 2:1000
  M(i) = M(i - 1) + 1;
  end

  for i = 2:1000
  M(i) = M(i - 1) + 1;
  end

  显然第二个程序的写法更不容易出问题。

  13、尽早为大的矩阵变量分配内存:Matlab使用heap method来管理内存。当Matlab的heap中没有足够的内存使用时,它会向系统请求内存;同时只要内存碎片可以存下当前的变量,Matlab会重新使用内存,而不用向系统申请内存。比较两个程序:

  a = rand(1e6,1);

  b = rand(1e6,1);
  # 使用大约15.4 MB RAM

  c = rand(2.1e6,1); #使用大约16.4 MB RAM


  a = rand(1e6,1);

  b = rand(1e6,1);
  clear
  c = rand(2.1e6,1);
  #使用大约32.4 MB RAM


  因为Matlab不能使用a、b被clear后空出的内存空间,因为它们均小于16.4 MB,而且它们也很可能是不连续的。因此最好的方法是首先为大矩阵分配内存:

  c = rand(2.1e6,1);
  clear
  a = rand(1e6,1);
  b = rand(1e6,1);
  # 使用16.4 MB RAM

  14、与上面2条近似的是:尽量避免产生大的瞬时变量,而且当它们不再使用时应该及时clear掉释放内存空间;同时尽量重复地使用变量,减少变量,保证内存的充分利用(和clear的作用差不多)。

  来源:CSDN网holybin的博客

最新评论

返回顶部