主要内容

高效使用内存的策略

这个主题解释了几个技术,以使用内存在MATLAB有效®

使用适当的数据存储

MATLAB提供了不同大小的数据类,例如uint8,因此您不需要使用大型类来存储较小的数据段。例如,使用该方法存储1,000个小的无符号整数值只需要7 KB的内存uint8而不是和它一起

使用适当的数值类

你在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('large_file_of_uint8s.bin', 'r');A = fread(fid, 1e3, 'uint8');% require 8k whos a Name Size Bytes Class Attributes a 1000x1 8000 double a = fread(fid, 1e3, 'uint8=>uint8');%需要1k谁是一个名称大小字节类属性1000x1 1000 uint8

尽可能使数组稀疏

如果您的数据包含许多零,则考虑使用稀疏数组,它只存储非零元素。下面的示例比较了稀疏和完整的存储需求:

一个=眼(1000);%对角为1的满矩阵=稀疏矩阵(A);类属性A 1000x1000 8000000 double As 1000x1000 24008 double Sparse

您可以看到,这个数组作为稀疏矩阵存储时只需要大约24 KB,而作为完整矩阵存储时则需要大约8 MB。一般来说,对于稀疏双数组用nnz非零元素和ncol列时,所需内存为:

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

请注意,MATLAB支持稀疏数组的万博1manbetx大多数(但不是全部)数学运算。

避免数据的临时副本

通过避免创建不必要的数据临时副本,可以显著减少所需的内存量。

避免创建临时数组

避免创建大的临时变量,并在不再需要临时变量时清除它们。例如,这段代码创建了一个存储为临时变量的零数组一个,然后转换一个单精度:

一个= 0 (1)e6, 1);=单(A);

使用一个命令来执行两个操作会更有效率:

= 0 (1 e6, 1, '单');

使用repmat函数、数组预分配和循环是处理非双精度数据而不需要内存中临时存储的其他方法。

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

在处理大型数据集时,请注意,如果被调用的函数修改了输入变量的值,则MATLAB会临时复制输入变量。这暂时使存储数组所需的内存翻倍,如果没有足够的内存可用,会导致MATLAB产生错误。

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

函数myfun A = magic(500);函数setrowval(row,value) A(row,:) = value;结束结束

回收使用的内存

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

定期将大数据保存到磁盘

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

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

当您重复或交互地处理一个非常大的数据集时,首先清除旧变量,为新变量腾出空间。否则,在覆盖变量之前,MATLAB需要相等大小的临时存储空间。例如,

兰德(1 = e5);b =兰德(1 e5);内存不足。更多信息clear a a = rand(1e5);%新数组

相关的话题