主要内容

解决“内存不足”错误

问题

当您的代码对大量数据进行操作或不能有效地使用内存时,MATLAB®可能会在响应不合理的数组大小时产生错误,或者可能会耗尽内存。MATLAB内置了防止创建太大数组的保护。例如,这段代码会导致一个错误,因为MATLAB无法创建具有所请求元素数量的数组。

A = rand(1e9);
请求的数组超过了最大可能的变量大小。

默认情况下,MATLAB可以使用高达100%的计算机RAM(不包括虚拟内存)来为数组分配内存,如果数组大小超过该阈值,则MATLAB会产生错误。例如,这段代码试图创建一个大小超过最大数组大小限制的数组。

B = rand(1e6);
请求的1000000x1000000 (7450.6GB)数组超过最大数组大小首选项(63.7GB)。这可能会导致MATLAB变得无响应。

如果关闭数组大小限制MATLAB工作空间首选项,尝试创建一个不合理的大数组可能会导致MATLAB耗尽内存,或者它可能会使MATLAB甚至您的计算机由于过度的内存分页(即在RAM和磁盘之间移动内存页)而无响应。

B = rand(1e6);
内存不足。

可能的解决方案金宝搏官方网站

无论您如何遇到内存限制,MATLAB都根据您的情况和目标提供了几种解决方案。金宝搏官方网站例如,您可以改进代码使用内存的方式,利用数据存储和数组等专门的数据结构,利用计算集群中的池化资源,或者调整您的设置和首选项。

请注意

这里给出金宝搏官方网站的解决方案是针对MATLAB的。要优化系统范围内的内存性能,请考虑向计算机添加更多的物理内存(RAM),或者在操作系统级别进行调整。

清除不再需要的变量

当不再需要变量时,将其清除成为一种习惯。要从内存中清除项,请使用清晰的函数。

之前
A = rand(1e4);disp (max ([],“所有”B = rand(1e4);
A = rand(1e4);disp (max ([],“所有”)明确一个B = rand(1e4);

有关更多信息,请参见有效使用内存的策略

使用适当的数据存储

不同的MATLAB数据类型对内存的要求不同。您可以通过使用适当的数据类型和存储来减少代码所使用的内存量。有关本节中解决方案的详细信息,请参见金宝搏官方网站有效使用内存的策略

使用合适的数字类。您应该使用的数字类取决于您的预期操作。在MATLAB中,是默认的数字数据类型,并为大多数计算任务提供足够的精度:

  • 如果要执行复杂的数学运算,如线性代数,请在双精度()或单精度()的格式。型号数量需要的内存比类型的数字少,但其表示精度也较低。

  • 如果您只需要进行简单的算术运算,并将原始数据表示为整数,请使用MATLAB中的整数类。

类别(数据类型) 字节 金宝app支持的操作
4 大多数数学
8 所有的数学
逻辑 1 逻辑/条件操作
int8, uint8 1 算术和一些简单的函数
int16, uint16 2 算术和一些简单的函数
int32, uint32 4 算术和一些简单的函数
int64, uint64 8 算术和一些简单的函数

减少存储数据时的开销。当您创建一个数字或字符数组时,MATLAB会分配一块内存来存储数组数据。MATLAB还将有关数组数据的信息,例如其类和维度,存储在一个称为a的小的独立内存块中.因为简单的数字和字符数组的开销最小,所以尽可能使用它们。只有对于过于复杂而不能存储在简单数组中的数据,才使用其他数据结构。

对于结构和单元数组,MATLAB不仅为数组创建一个头,而且为结构的每个字段或单元数组的每个单元创建一个头。因此,存储结构体或单元格数组所需的内存量不仅取决于它包含多少数据,还取决于它是如何构造的。因此,包含许多小元素的单元格数组或包含少量内容的许多字段的结构具有很大的开销,应该避免使用。

之前
% S有15,000个字段(每个数组元素3个字段)I = 1:100j = 1:50 S(i,j)。R = 0;%每个字段包含一个数字标量S (i, j)。G = 0;S (i, j)。B = 0;结束结束
% S有3个字段S.R = 0 (100,50);%每个字段包含一个数字数组S.G = 0 (100,50);S.B = 0 (100,50);

尽可能使数组稀疏。一个好的做法是使用稀疏存储存储具有很少非零元素的矩阵。当一个完整矩阵具有少量非零元素时,将矩阵转换为稀疏存储通常会改善内存使用和代码执行时间。MATLAB有几个支持稀疏存储的函数。金宝app例如,您可以使用speye函数创建一个稀疏的单位矩阵。

之前
I = eye(1000);
I = speye(1000);

使用适当的MATLAB类导入数据。从二进制文件中读取数据时从文件中读,一个常见的错误是只指定文件中数据的类,而不指定MATLAB在工作空间中使用的数据的类。如果没有指定内存中数据的类,MATLAB将使用即使读取的是8位值。

之前
fileID = fopen(“large_file_of_uint8s.bin”“r”);A = readad (fileID,1e3;“uint8”);
fileID = fopen(“large_file_of_uint8s.bin”“r”);A = readad (fileID,1e3;“uint8 = > uint8”);

避免不必要的数据拷贝

要提高内存使用和执行速度,请确保代码不会产生不必要的数据副本。有关本节中解决方案的详细信息,请参见金宝搏官方网站避免不必要的数据拷贝有效使用内存的策略

避免创建临时阵列。避免在不必要的时候创建临时数组。例如,不是创建一个零数组作为临时变量,然后将该变量传递给函数,而是使用一个命令来完成这两个操作。

之前
A = 0 (1,1);As = single(A);
As = 0 (1e6,1,“单身”);

Preallocate记忆。在处理大型数据集时,反复调整数组大小可能会导致程序耗尽内存。如果扩展数组超出其原始位置的可用连续内存,MATLAB必须复制该数组并将副本移动到具有足够空间的内存块中。在此过程中,内存中存在原始数组的两个副本。您可以通过预先分配数组所需的最大空间量来改善内存使用和代码执行时间。有关更多信息,请参见预先配置

之前
X = 0;K = 2:10000 x(K) = x(K -1) + 5;结束
X = 0 (1,1000000);K = 2:10000 x(K) = x(K -1) + 5;结束

使用嵌套函数传递更少的参数。当调用一个函数时,如果函数修改了它的值,MATLAB通常会在调用者的工作空间中临时复制该变量。MATLAB应用各种技术来避免不必要的复制,但避免输入变量的临时复制并不总是可能的。

在函数调用中避免临时拷贝的一种方法是使用嵌套函数。嵌套函数共享所有外部函数的工作空间,因此不需要在函数调用中传递变量的副本。有关更多信息,请参见嵌套函数

只加载你需要的数据

修复内存问题的一种方法是仅将您试图解决的问题所需的大型数据集导入MATLAB。当从数据库等源导入时,数据集大小通常不是问题,在数据库中,您可以显式搜索匹配查询的元素。但在加载大型平面文本或二进制文件时,这是一个常见的问题。

数据存储函数允许您以增量方式处理大型数据集。当您希望一次只将数据集的某些部分加载到内存中时,数据存储非常有用。

若要创建数据存储,请提供包含具有类似格式的文件集合的文件或目录的名称。例如,对于单个文件,使用以下命令。

Ds = datastore(“路径/ / file.csv”);
或者对于文件夹中的文件集合,使用以下方法。
Ds = datastore(“路径”/ /文件夹/);
还可以使用通配符*选择指定类型的所有文件。
Ds = datastore(“路径/ / * . csv”);
数据存储支持多种文件格金宝app式(表格数据、图像、电子表格等)。有关更多信息,请参见“文件格式”或“应用程序”选择“数据存储”

除了数据存储,MATLAB还有其他几个函数来加载部分文件。这个表根据函数操作的文件类型总结了这些函数。

文件类型 部分加载
MAT-file

方法创建的对象中创建索引,从而加载变量的一部分matfile函数。有关更多信息,请参见在mat文件中保存和加载变量的部分

文本

使用textscan函数通过仅读取选定的列和行来访问大型文本文件的部分。指定行数或重复格式数textscan, MATLAB计算事先所需的确切内存量。

二进制

您可以使用低级二进制文件I/O函数,例如从文件中读,以访问具有已知格式的任何文件的部分。对于未知格式的二进制文件,请尝试使用内存映射memmapfile函数。

图像,音频,视频和HDF

许多支持从这些类型的文件中加载的MATLAB函数允许您选择要读取的数金宝app据部分。详细信息请参见中各功能参考页面金宝app支持的文件格式导入和导出

使用Tall数组

高数组可以帮助您处理大到无法装入内存的数据集。MATLAB一次处理小块的数据,在后台自动处理所有的数据分块和处理。您可以通过两种主要方式使用tall数组:

  • 如果您有一个可以装入内存的大数组,但是在尝试执行计算时耗尽了内存,则可以将该数组强制转换为一个大数组。

    t = tall(A);
    这种方法允许您使用可以装入内存的大型数组,但是这些数组占用的内存太多,无法在计算期间复制数据。例如,如果您有8 GB的RAM和5 GB的矩阵,那么将矩阵转换为tall数组可以使您在矩阵上执行计算而不会耗尽内存。有关这种用法的示例,请参见

  • 如果您有基于文件或文件夹的数据,您可以创建一个数据存储,然后在数据存储之上创建一个tall数组。

    Ds = datastore(“路径/ / file.csv”);T = tall(ds);
    这种方法为您提供了MATLAB中tall数组的全部功能。数据可以有任意数量的行,并且MATLAB不会耗尽内存。因为数据存储可用于本地和远程数据位置,您使用的数据不需要在您用来分析它的计算机上。看到处理远程数据了解更多信息。

要了解有关高数组的更多信息,请参见内存外数据的Tall数组

使用多机内存

如果您有一个计算机集群,您可以使用分布式数组(需要Parallel Computing Toolbox™)来使用集群中所有机器的组合内存执行计算。根据数据在内存中的位置不同,存在不同的方法在并行池的工作线程之间对数据进行分区。有关更多信息,请参见将数组分发给并行工作者(并行计算工具箱)

调整设置和首选项

一般来说,重写代码是提高内存性能最有效的方法。但是,如果您不能更改代码,这些解决方案可能会为代码提供所需的内存量。金宝搏官方网站

开始MATLAB没有Java虚拟机或减少Java堆大小。如果你在没有Java的情况下启动MATLAB®虚拟机(JVM™)软件或减少Java堆大小,可以增加可用的工作空间内存。要启动没有JVM的MATLAB,请使用命令行选项-nojvm.有关如何减小Java堆大小的信息,请参见Java堆内存首选项

使用-nojvm代价是失去了一些依赖于JVM的特性,比如桌面工具和图形。从MATLAB开始-nodesktop选项不会节省大量的内存。

调整Array大小限制。如果遇到数组大小超过最大数组大小首选项的错误,可以在MATLAB中调整此数组大小限制。有关调整数组大小限制的信息,请参见工作空间和可变首选项.只有当您想要创建的数组超过当前最大数组大小限制,但又不是太大而无法装入内存时,此解决方案才有用。即使您关闭了数组大小限制,尝试创建一个不合理的大数组也可能导致MATLAB耗尽内存,或者它可能使MATLAB甚至您的计算机由于过多的内存分页而无响应。

另请参阅

|||

相关的话题