有效使用记忆的策略
本主题解释了在MATLAB中有效使用内存的几种技术®.
使用适当的数据存储
MATLAB为您提供了不同大小的数据类,例如双
而且uint8
,因此您不需要使用大型类来存储较小的数据段。方法存储1,000个小型无符号整型值所需的内存减少了7 KBuint8
类双
.
使用适当的数字类
在MATLAB中应该使用的数值类取决于您的预期操作。默认类双
提供最好的精度,但每个元素需要存储8个字节的内存。如果您打算执行复杂的数学(如线性代数),则必须使用浮点类(如双
或单
.的单
类只需要4个字节。属性的操作有一些限制单
类,但大多数MATLAB数学操作支持。金宝app
如果您只需要进行简单的算术运算,并将原始数据表示为整数,则可以使用MATLAB中的整数类。下面是数字类、内存需求(以字节为单位)和支持的操作的列表。金宝app
类别(数据类型) | 字节 | 金宝app支持的操作 |
---|---|---|
单 |
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, 1e3, 'uint8');%需要8k谁的名字大小字节类属性一个1000x1 8000双a = fread(fid, 1e3, 'uint8=>uint8');%需要1k谁的名字大小字节类属性1000x1 1000uint8
尽可能使数组稀疏
如果您的数据包含许多零,请考虑使用稀疏数组,它只存储非零元素。下面的例子比较了稀疏存储和全存储需求:
A =眼睛(1000);%对角线上有1的完整矩阵As =稀疏(A);%稀疏矩阵,只有非零元素,其名称大小字节类属性A 1000x1000 8000000 double As 1000x1000 24008 double Sparse
可以看到,这个数组作为稀疏数组存储时只需要大约24 KB,而作为完整矩阵存储时则需要大约8 MB。一般来说,对于稀疏双数组用nnz
非零元素和ncol
列,所需内存为:
16 *
nnz
+ 8 *ncol
+ 8字节(在64位机器上)
请注意,MATLAB支持稀疏数组上金宝app的大部分(但不是全部)数学运算。
避免数据的临时副本
通过避免创建不必要的数据临时副本,可以显著减少所需的内存量。
避免创建临时数组
避免创建大型临时变量,并在不再需要临时变量时将其清除。例如,这段代码创建了一个零数组,存储为临时变量一个
,然后转换一个
单精度:
A = 0 (1e6,1);As =单(A);
使用一个命令来执行这两个操作会更节省内存:
A = 0 (1e6,1,'single');
使用嵌套函数来传递更少的参数
在处理大型数据集时,请注意,如果被调用的函数修改了输入变量的值,MATLAB会对输入变量进行临时复制。这将使存储数组所需的内存暂时增加一倍,如果没有足够的内存可用,这将导致MATLAB生成错误。
在这种情况下使用较少内存的一种方法是使用嵌套函数。嵌套函数共享所有外部函数的工作空间,使嵌套函数能够访问其通常作用域之外的数据。在这里显示的例子中,嵌套函数setrowval
是否可以直接访问外部函数的工作空间myfun
,这样就不需要在函数调用中传递变量的副本。当setrowval
的值一个
,它在调用函数的工作区中修改它。不需要使用额外的内存为被调用的函数保存单独的数组,也不需要返回修改后的值一个
:
函数myfun A =魔术(500);setrowval(400,0) disp(' A(399:401,1:10)的新值是')A(399:401,1:10)函数setrowval(row,value) A(row,:) = value;结束结束
回收已用内存
增加可用内存量的一个简单方法是清除不再使用的大型数组。
定期将大数据保存到磁盘
如果您的程序生成非常大量的数据,请考虑定期将数据写入磁盘。保存该部分数据后,使用清晰的
函数从内存中删除变量并继续数据生成。
清除内存中不再需要的旧变量
当您重复或交互式地处理一个非常大的数据集时,请先清除旧变量,为新变量腾出空间。否则,MATLAB在重写变量之前需要相等大小的临时存储。例如,
A = rand(1e5);B = rand(1e5);内存不足。更多信息清楚a a = rand(1e5);%新数组