文档

有效使用内存的策略

减少所需内存量的方法

许多“内存不足”问题的根源通常涉及分析或处理现有的大量数据,比如文件或数据库中的数据。这需要将所有或部分数据集放入MATLAB中®软件过程。以下技术处理在此阶段最小化所需内存的问题。

只装载尽可能多的数据,你需要

在MATLAB中只导入您想要解决的问题所需的大量数据集。在从数据源(如数据库)导入时,这通常不是问题,在数据库中可以显式地搜索与查询匹配的元素。但这是加载大型纯文本或二进制文件时常见的问题。不要加载整个文件,使用适当的MATLAB函数来加载文件的部分。

文件类型 部分加载
MAT-file

属性创建的对象中创建索引,从而加载变量的一部分matfile函数。

文本

使用textscan函数通过只读选定的列和行来访问大文本文件的某些部分。如果指定的行数或重复格式编号textscan, MATLAB可以计算出预先需要的确切内存量。

二进制

你可以使用低级别的二进制文件I / O功能,如从文件中读,以访问任何具有已知格式的文件的部分。对于未知格式的二进制文件,尝试使用内存映射memmapfile函数。

图片,HDF,音频和视频

许多MATLAB功能,从这些类型的文件支持加载允许您选择部分数据读取万博1manbetx。有关详细信息,请参见功能参考页中列出万博1manbetx支持的文件格式的导入和导出

按块处理数据

考虑块处理,即,处理大的数据在一个循环时间设定一个部分。在数据集减少最大数组的大小减少了所需的任何副本或临时变量的大小。您可以使用以下两种方法之一这项技术:

  • 对于可以分解为独立块和独立处理的应用程序子集。

  • 用于只依赖于前一个块的状态的应用程序,如过滤。

避免创建临时数组

避免造成大的临时变量,也使它成为一个惯例,清除你使用这些临时变量的时候都不再需要。例如,当您创建的,而不是保存到一个临时变量大阵零,一个,然后转换一个一个:

A =零(1e6,1);正如=单(A);

只使用一个命令来做两种操作:

A =零(1e6,1, '单');

使用repmat函数、数组预分配和循环是另一种工作方式nondouble数据,而无需在存储器中的临时存储。

使用嵌套函数传递更少的参数

当使用大型数据集,要知道,MATLAB进行输入变量的临时副本,如果被调用的函数修改它的值。这将暂时加倍到存储阵列,这引起MATLAB来产生一个错误,如果没有足够的内存可用所需的内存。

在这种情况下使用更少内存的一种方法是使用嵌套函数。嵌套函数共享所有外部函数的工作空间,使嵌套函数可以访问其通常作用域之外的数据。在这里显示的示例中,是嵌套函数setrowval是否可以直接访问外部函数的工作空间myfun,使得不必传递变量的副本在函数调用。什么时候setrowval的值一个,它在调用函数的工作区中修改它。不需要使用额外的内存来保存被调用函数的单独数组,也不需要返回修改后的值一个

函数myfun A = magic(500);函数setrowval(row, value) = value;结束setrowval (400 0);disp('The new value of A(39:401,1:10) is') A(39:401,1:10)结束

使用适当的数据存储

MATLAB提供了不同大小的数据类的,如uint8,所以你并不需要使用大量的类来存储数据,你的小片段。例如,它需要7 KB更少的存储器来存储使用1000个小无符号整数值uint8类比它与

使用适当的数字类

在MATLAB中应该使用的numeric类取决于预期的操作。默认的类提供了最佳的精度,但需要每个内存元素存储8字节。如果您打算执行复杂的数学(如线性代数),则必须使用浮点类(如a)。该类只需要4个字节。有一些限制,您可以做什么类,但是支持大多数MATLAB数学操作。万博1manbetx

如果您只需要执行简单的算术,并且将原始数据表示为整数,那么您可以使用MATLAB中的整数类。下面是数字类、内存需求(以字节为单位)和支持的操作的列表。万博1manbetx

类(数据类型) 字节 万博1manbetx支持的操作
4 大多数数学
8 所有的数学
合乎逻辑 1 逻辑/条件操作
INT8,UINT8 1 算术和一些简单的函数
INT16,UINT16 2 算术和一些简单的函数
int32, uint32 4 算术和一些简单的函数
int64, int64 8 算术和一些简单的函数

减少存储数据时的开销

MATLAB数组(内部实现为mxArrays)要求的空间来存储关于在存储器中的数据,例如类型,尺寸,和属性的元信息。这大约需要每阵列80个字节。当你有大量的小(例如,几百或几千个)这仅开销成为问题mxArrays(例如,标量)。该谁是命令将列出变量使用的内存,但不包括这方面的开销。

因为简单的数字数组(包含1)mxArray)有最少的开销,你应该尽可能地使用它们。当数据太复杂而无法用简单数组(或矩阵)存储时,可以使用其他数据结构。

单元阵列是由单独的mxArrays为每个元素。因此,包含许多小元素的单元格阵列开销很大。

结构对每个字段的开销要求相似(参见数组头)。与许多领域和含量少的结构有一个大的开销,应当避免。大阵列用数字标量场结构的需要比用含有大数字数组字段的结构更多的内存。

还注意,虽然在连续的存储器MATLAB存储数字数组,这是不适合的结构和单元阵列的情况。

将数据导入到适当的位置MATLAB

当从二进制文件读取数据时从文件中读,通常的错误是只指定文件中数据的类,而一旦数据在工作空间中,则不指定MATLAB使用的数据的类。因此,默认值用于即使你正在阅读只有8位值。例如,

fid = fopen (large_file_of_uint8s。本”、“r”);a = fread(fid, 1e3, 'uint8');%需要8k的名称大小字节类属性一个1000x1 8000双a = fread(fid, 1e3, 'uint8=>uint8');%需要一个名称大小字节类属性为1000x1 1000uint8

尽可能使数组稀疏

如果数据包含许多零,考虑使用稀疏数组,它只存储非零元素。下面的例子比较了一个以零为主的数组存储所需的空间:

A =眼(1000);与对角线上的那些由于=稀疏(A)%全矩阵;%稀疏矩阵仅非零元素卫生组织名称大小字节类属性的1000×1000 8000000双如1000×1000 24008双疏

您可以看到,这个数组稀疏存储大约需要4 KB,但完整矩阵大约需要8 MB。一般来说,用于稀疏双数组nnz非零元素和的NcoI列,所需的内存是

  • 16 *nnz+ 8 *的NcoI+ 8字节(在64位机器上)

  • 12 *nnz+ 4 *的NcoI+ 4个字节(32位机器上)

需要注意的是MATLAB不支持稀疏数组所有的数学运算万博1manbetx。

如何避免破碎记忆

MATLAB总是使用一个连续的内存段来存储一个数字数组。但是,当您操作此数据时,连续的块可能会变成碎片。当内存被分段时,可能有足够的空闲空间,但没有足够的连续内存来存储新的大变量。增加碎片使用的内存会大大超过需要。

在创建数组时预先分配连续内存

在MATLAB会话的过程中,内存会由于动态内存分配和释放而变得碎片化。循环,即逐步增加,或增长,每次通过循环的数据结构的大小会增加这个碎片,因为它们必须反复查找和分配更大的内存块来存储数据。

为了更有效地使用你的记忆中,预分配内存足够大的块以最终大小在进入循环之前举行的矩阵。当你预分配内存的数组,在计算的开始,整个全尺寸阵列MATLAB储备足够的连续空间。一旦你有了这个空间,你可以添加元素的数组,而无需在内存中为它分配不断新的空间。

有关预先分配的更多信息,请参见预先配置

分配你的更大的阵列第一

MATLAB使用堆方法进行内存管理。当堆中没有足够的可用内存来存储当前变量时,它向操作系统请求内存。只要堆中可用所需的内存段大小,它就会重用内存。

下面的语句大约需要4.3 MB的RAM。这是因为在为一个2.3 MB的数组分配空间时,MATLAB可能无法重用之前被两个1 MB数组占用的空间:

一个=兰德(1)e6, 1);b =兰德(1 e6, 1);c = rand(2.3e6,1);

防止内存过度分配的最简单方法是首先分配最大的向量。这些语句只需要大约2.0 MB的RAM:

C =兰特(2.3e6,1);清除=兰特(1e6,1);B =兰特(1e6,1);

长期使用(窗户系统只有)

在32位微软®窗户®,由于Windows内存管理器没有返回某些类型和大小的块给操作系统,MATLAB的工作空间可能会随着时间的推移而分裂。清除MATLAB工作区并不能解决这个问题。您可以通过先分配最大的变量来最小化问题。然而,这并不能解决工作空间的碎片问题,例如,由于连续使用MATLAB长达数天或数周而导致的碎片问题。唯一的解决方案是保存您的工作并重新启动MATLAB。

命令将所有变量保存到磁盘并将它们加载回磁盘,但对于这种情况没有帮助。

回收使用的内存

增加可用内存量的一个简单方法是清除不再使用的大型数组。

定期将大数据保存到磁盘

如果您的程序生成非常大量的数据,考虑定期将数据写入磁盘。保存该部分数据后,使用清晰的函数来从内存中删除变量并继续数据生成。

从内存中清除旧变量不再需要时

当你是一个非常大的数据重复或交互设置工作,首先清除旧的变量,以腾出空间为新变量。否则,MATLAB需要重写变量之前相同大小的临时存储。例如,

一个=兰特(100e6,1)%800 MB数组b =兰特(100e6,1)%新800 MB阵列使用的存储器兰特超时错误。键入帮助记忆你的选择。清除一个=兰特(100e6,1)%新800 MB阵列
这个话题有用吗?