主要内容

解决“内存不足”错误

问题

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

兰德(1 = e9);
所请求的数组超过了可能的最大可变大小。

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

B =兰德(1 e6);
请求的1000000x1000000 (7450.6GB)数组超过了最大数组大小首选项(63.7GB)。这可能会导致MATLAB失去响应。

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

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

可能的解决方案

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

请注意

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

清除不再需要的变量

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

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

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

使用适当的数据存储

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

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

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

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

类(数据类型) 字节 支持的操作
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:10 0j = 1:50 S(i,j)。R = 0;每个字段包含一个数字标量S (i, j)。G = 0;S (i, j)。B = 0;结束结束
% S有3个字段50 S.R = 0 (100);每个字段包含一个数字数组50 S.G = 0 (100);mit获得= 0(100年,50);

尽可能使数组稀疏。一个好的实践是使用稀疏存储来存储非零元素较少的矩阵。当一个完整的矩阵有少量非零元素时,将矩阵转换为稀疏存储通常会提高内存使用和代码执行时间。MATLAB有几个支持稀疏存储的函数。例如,您可以使用speye函数来创建一个稀疏单位矩阵。

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

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

之前
文件标识= fopen (“large_file_of_uint8s.bin”“r”);一个=从文件中读(文件标识,1 e3,“uint8”);
文件标识= fopen (“large_file_of_uint8s.bin”“r”);一个=从文件中读(文件标识,1 e3,“uint8 = > uint8”);

避免不必要的数据拷贝

要提高内存使用和执行速度,请确保您的代码不会导致不必要的数据拷贝。有关本节中解决方案的更多信息,请参见避免不必要的数据拷贝而且有效使用内存的策略

避免创建临时数组。避免在不必要的情况下创建临时数组。例如,与其创建一个由0组成的数组作为临时变量,然后将该变量传递给函数,不如使用一个命令来执行这两种操作。

之前
一个= 0 (1)e6, 1);=单(A);
当= 0 (1 e6, 1“单身”);

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

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

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

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

只加载你需要的数据

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

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

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

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

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

文件类型 部分加载
MAT-file

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

文本

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

二进制

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

图像,音频,视频和HDF

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

使用高的数组

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

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

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

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

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

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

使用多台机器的内存

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

调整设置和首选项

通常,重写代码是提高内存性能最有效的方法。但是,如果您不能更改代码,这些解决方案可以为其提供所需的内存数量。

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

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

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

另请参阅

|||

相关的话题

Baidu
map