许多“内存不足”问题的根源通常涉及分析或处理现有的大量数据,比如文件或数据库中的数据。这需要将所有或部分数据集放入MATLAB中®软件过程。以下技术处理在此阶段最小化所需内存的问题。
在MATLAB中只导入您想要解决的问题所需的大量数据集。在从数据源(如数据库)导入时,这通常不是问题,在数据库中可以显式地搜索与查询匹配的元素。但这是加载大型纯文本或二进制文件时常见的问题。不要加载整个文件,使用适当的MATLAB函数来加载文件的部分。
文件类型 | 部分加载 |
---|---|
MAT-file | 属性创建的对象中创建索引,从而加载变量的一部分 |
文本 | 使用 |
二进制 | 你可以使用低级别的二进制文件I / O功能,如 |
图片,HDF,音频和视频 | 许多MATLAB功能,从这些类型的文件支持加载允许您选择部分数据读取万博1manbetx。有关详细信息,请参见功能参考页中列出万博1manbetx支持的文件格式的导入和导出。 |
考虑块处理,即,处理大的数据在一个循环时间设定一个部分。在数据集减少最大数组的大小减少了所需的任何副本或临时变量的大小。您可以使用以下两种方法之一这项技术:
对于可以分解为独立块和独立处理的应用程序子集。
用于只依赖于前一个块的状态的应用程序,如过滤。
避免造成大的临时变量,也使它成为一个惯例,清除你使用这些临时变量的时候都不再需要。例如,当您创建的,而不是保存到一个临时变量大阵零,一个
,然后转换一个
一个:
A =零(1e6,1);正如=单(A);
只使用一个命令来做两种操作:
A =零(1e6,1, '单');
当使用大型数据集,要知道,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使用的数据的类。因此,默认值双
用于即使你正在阅读只有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阵列