有效利用内存的策略
该主题解释了在MATLAB中有效使用内存的几种技术®。
使用适当的数据存储
MATLAB为您提供不同尺寸的数据类,例如双倍的
和UINT8
,因此您无需使用大型类来存储较小的数据。例如,使用该存储1,000个小的无符号整数值所需的记忆少7 kbUINT8
班级比上课双倍的
。
使用适当的数字类
您在MATLAB中使用的数字类取决于您的预期操作。默认类双倍的
给出最佳的精度,但是每个内存元素需要8个字节才能存储。如果您打算执行复杂的数学(例如线性代数),则必须使用浮点类类,例如双倍的
或者单身的
。这单身的
课程仅需要4个字节。您可以做些什么单身的
课程,但大多数MATLAB数学操作都得到了支持。万博1manbetx
如果您只需要执行简单的算术,而将原始数据表示为整数,则可以在MATLAB中使用整数类。以下是数字类,内存需求(字节)和受支持的操作的列表。万博1manbetx
类(数据类型) | 字节 | 万博1manbetx支持操作 |
---|---|---|
单身的 |
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('name_file_of_uint8s.bin','r');a = fread(fid,1e3,'uint8');%需要8K名称大小字节类属性a 1000x1 8000 double a = fread(fid,1e3,'uint8 => uint8');%需要1K的名称大小字节类属性A 1000x1 1000 UINT8
尽可能使阵列稀疏
如果您的数据包含许多零,请考虑使用仅存储非零元素的稀疏数组。以下示例比较稀疏和完整的存储要求:
a =眼(1000);%全矩阵,对角上的矩阵为=稀疏(a);%稀疏矩阵只有非零元素whos名称大小字节类属性A 1000x1000 8000000 double as 1000x1000 24008双稀疏
您可以看到,此数组仅需要约24 kb的稀疏存储,但大约需要8 MB作为完整矩阵。通常,对于稀疏的双阵列NNZ
非零元素和NCOL
列,所需的内存是:
16 *
NNZ
+ 8 *NCOL
+ 8个字节(在64位机器上)
请注意,MATLAB在稀疏阵列上支万博1manbetx持大多数但不是全部的数学操作。
避免临时数据副本
您可以通过避免创建不必要的数据副本来显着减少所需的内存量。
避免创建临时数组
避免创建大型临时变量,并使其在不再需要时清除临时变量的习惯。例如,此代码创建一个存储为临时变量的零数组一个
,然后转换一个
到单精制:
a =零(1E6,1);as = single(a);
使用一个命令进行两个操作是更有效的内存效率:
a = zeros(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(行,值)价值;结尾
回收使用的内存
增加可用内存量的一种简单方法是清除您不再使用的大型阵列。
定期将大数据保存到磁盘
如果您的程序生成大量数据,请考虑定期将数据写入磁盘。保存该数据的部分后,请使用清除
功能以从内存中删除变量并继续数据生成。
不再需要时从内存中清除旧变量
当您重复或互动地使用非常大的数据集时,请先清除旧变量以为新变量腾出空间。否则,MATLAB需要在覆盖变量之前临时存储相等的大小。例如,
a = rand(1e5);b = rand(1e5);记不清。更多信息清除a = rand(1e5);%新数组