主要内容

解决“内存不足”错误

问题

当您的代码操作大量数据或没有有效地使用内存时,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中的整数类。

类别(数据类型) 字节 万博1manbetx支持的操作
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有几个支持稀疏存储的函数。万博1manbetx例如,您可以使用speye函数创建一个稀疏单位矩阵。

之前
I =眼睛(1000);
I = speye(1000);

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

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

避免不必要的数据拷贝

为了提高内存使用和执行速度,请确保您的代码不会导致不必要的数据复制。有关本节中的解决方案的详细信息,请参见万博 尤文图斯避免不必要的数据拷贝而且有效使用记忆的策略

避免创建临时数组。避免在不需要时创建临时数组。例如,与其创建一个0数组作为临时变量,然后将该变量传递给一个函数,不如使用一个命令来完成这两个操作。

之前
A = 0 (1e6,1);As =单(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。从数据库等数据源导入数据集时,数据集大小通常不是问题,您可以显式地搜索与查询匹配的元素。但这是加载大型平面文本或二进制文件的常见问题。

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

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

数据存储(“路径/ / file.csv”);
或使用文件夹中的文件集合,使用以下方法。
数据存储(“路径”/ /文件夹/);
也可以使用通配符*选择特定类型的所有文件。
数据存储(“路径/ / * . csv”);
数据存储支持各种各样的万博1manbetx文件格式(表格数据、图像、电子表格等等)。有关更多信息,请参见选择“文件格式”或“应用程序”的数据存储

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

文件类型 部分加载
MAT-file

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

文本

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

二进制

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

图像,音频,视频和HDF

许多支持从这些类型的文件加载的MATLAB函数允许您选择要读取的数据万博1manbetx部分。详细信息请参见万博1manbetx导入和导出支持的文件格式

使用高数组

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

  • 如果您有一个适合内存的大数组,但在尝试执行计算时内存不足,则可以将该数组强制转换为高数组。

    t =高(A);
    这种方法允许您使用能够容纳内存的大型数组,但在计算过程中会消耗太多的内存来允许数据的复制。例如,如果您有8 GB的RAM和5 GB的矩阵,那么将矩阵转换为高数组可以使您在不耗尽内存的情况下对矩阵执行计算。有关此用法的示例,请参见

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

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

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

使用多台机器的内存

如果您有一个计算机集群,您可以使用分布式阵列(需要并行计算工具箱™)使用集群中所有计算机的组合内存执行计算。根据数据在内存中的适合程度,存在不同的方法在并行池的worker之间划分数据。有关更多信息,请参见将数组分发给并行工作者(并行计算工具箱)

调整设置和首选项

一般来说,重写代码是提高内存性能最有效的方法。但是,如果不能对代码进行更改,这些解决方案可以为代码提供所需的内存量。万博 尤文图斯

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

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

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

另请参阅

|||

相关的话题