有效使用内存的策略
本主题解释了在MATLAB中有效使用内存的几种技术®.
使用适当的数据存储
MATLAB提供了不同大小的数据类,例如双
而且uint8
,因此不需要使用大的类来存储较小的数据段。方法存储1,000个小的无符号整数值所需的内存减少了7 KBuint8
比它所使用的双
.
使用适当的数字类
你应该在MATLAB中使用的数值类取决于你想要的操作。默认的类双
提供最好的精度,但是每个内存元素需要8个字节来存储。如果打算执行复杂的数学运算,如线性代数,则必须使用浮点类,如双
或单
.的单
类只需要4个字节。的功能有一些限制单
类,但大多数MATLAB数学操作是支持的。
如果只需要进行简单的算术运算,并且将原始数据表示为整数,则可以使用MATLAB中的整数类。下面是数字类、内存需求(以字节为单位)和支持的操作的列表。
类(数据类型) | 字节 | 支持的操作 |
---|---|---|
单 |
4 | 大多数数学 |
双 |
8 | 所有的数学 |
逻辑 |
1 | 逻辑/条件操作 |
int8, uint8 |
1 | 算术和一些简单的函数 |
int16, uint16 |
2 | 算术和一些简单的函数 |
int32, uint32 |
4 | 算术和一些简单的函数 |
int64, uint64 |
8 | 算术和一些简单的函数 |
降低存储数据时的开销
MATLAB数组(内部实现为mxArrays
)需要在内存中存储关于数据的元信息的空间,例如类型、维度和属性。每个数组大约需要104字节。只有当您有大量(例如,数百或数千)的小开销时,这个开销才会成为问题mxArrays
(例如,标量)。的谁
命令列出变量使用的内存,但不包括此开销。
因为简单的数值数组(包含一个mxArray
)的开销最少,你应该在任何可能的地方使用它们。当数据太复杂而无法存储在简单数组(或矩阵)中时,可以使用其他数据结构。
单元格阵列由独立的mxArrays
为每个元素。因此,包含许多小元素的单元格数组有很大的开销。
结构的每个字段需要类似的开销。具有许多字段和小内容的结构有很大的开销,应该避免使用。具有数值标量字段的大型数组结构比包含大型数值数组的字段结构需要更多的内存。
还要注意的是,虽然MATLAB在连续内存中存储数值数组,但对于结构和单元格数组却不是这样。有关更多信息,请参见MATLAB如何分配内存.
导入数据到适当的MATLAB类
从二进制文件中读取数据时从文件中读
,如果只指定文件中数据的类,而不指定MATLAB在工作空间中使用的数据的类,这是一个常见的错误。因此,默认双
即使只读取8位值也使用。例如,
Fid = fopen('large_file_of_uint8 .bin', 'r');A = fread(fid, 13e3, 'uint8');%需要8k whos名称大小字节类属性a 1000x1 8000双a = fread(fid, 1e3, 'uint8=>uint8');%需要1k whos一个名称大小字节类属性1000x1 1000 uint8
尽可能使数组稀疏
如果您的数据包含许多0,请考虑使用稀疏数组,它只存储非零元素。下面的例子比较了稀疏存储需求和全存储需求:
一个=眼(1000);%对角线上有1的满矩阵As =稀疏(A);%只有非零元素的稀疏矩阵,其名称大小字节类属性A 1000x1000 8000000 double As 1000x1000 24008双稀疏
您可以看到,这个数组作为稀疏存储只需要大约24 KB,而作为完整矩阵存储大约需要8 MB。一般来说,对于稀疏双数组nnz
非零元素和ncol
列,所需内存为:
16 *
nnz
+ 8 *ncol
+ 8字节(在64位机器上)
注意,MATLAB支持稀疏数组上的大多数(但不是全部)数学运算。
避免临时复制数据
通过避免创建不必要的数据临时副本,可以显著减少所需的内存量。
避免创建临时数组
避免创建较大的临时变量,并在不再需要临时变量时将其清除。例如,这段代码创建了一个存储为临时变量的0数组一个
,然后转换一个
单精度:
一个= 0 (1)e6, 1);=单(A);
使用一个命令同时执行两个操作会更节省内存:
= 0 (1 e6, 1, '单');
使用嵌套函数传递更少的参数
在处理大型数据集时,要注意,如果调用的函数修改了输入变量的值,MATLAB会生成输入变量的临时副本。这将暂时使存储数组所需的内存翻倍,如果没有足够的内存可用,这将导致MATLAB产生错误。
在这种情况下使用更少内存的一种方法是使用嵌套函数。嵌套函数共享所有外部函数的工作空间,使嵌套函数能够访问其通常作用域之外的数据。在这里显示的示例中,嵌套函数setrowval
是否可以直接访问外部功能的工作空间myfun
,因此无需在函数调用中传递该变量的副本。当setrowval
修改的值一个
,它在调用函数的工作空间中修改它。不需要使用额外的内存为被调用的函数保存单独的数组,也不需要返回修改后的值一个
:
函数myfun A = magic(500);函数setrowval(row,:) = value;结束结束
回收使用的内存
增加可用内存量的一个简单方法是清除不再使用的大型数组。
定期将大数据保存到磁盘
如果您的程序生成大量数据,请考虑定期将数据写入磁盘。在保存该部分数据之后,使用清晰的
函数从内存中删除变量并继续生成数据。
清除内存中不再需要的旧变量
当您重复或交互地处理非常大的数据集时,请首先清除旧变量,为新变量腾出空间。否则,MATLAB在重写变量之前需要相同大小的临时存储。例如,
兰德(1 = e5);b =兰德(1 e5);内存不足。更多信息清晰a a = rand(1e5);%新数组