MATLAB如何分配内存
数组的内存分配
下面的主题提供了MATLAB如何®软件在处理数组和变量时分配内存。目的是帮助您在编写代码时更有效地使用内存。然而,大多数时候,您不应该关心这些内部操作,因为MATLAB会自动为您处理数据存储。
请注意
关于MATLAB软件如何内部处理数据的任何信息都可能在未来的版本中更改。
创建和修改array
当您将数值或字符数组分配给变量时,MATLAB分配一个连续的虚拟内存块,并将数组数据存储在该块中。MATLAB还将关于数组数据的信息,例如它的类和维度,存储在一个单独的小内存块中,称为头.
如果向现有数组中添加新元素,MATLAB将以一种保持存储连续的方式扩展内存中的现有数组。这通常需要找到一个足够大的新内存块来容纳展开的数组。然后MATLAB将数组的内容从其原始位置复制到内存中的这个新块中,将新元素添加到该块中的数组中,并释放内存中的原始数组位置。
如果从现有数组中删除元素,MATLAB将通过删除被删除的元素来保持内存存储连续,然后将其存储压缩到原始内存位置。
处理大型数据集。如果您正在处理大型数据集,那么在增加数组的大小时需要非常小心,以避免由于内存不足而导致错误。如果将数组扩展到其原始位置的可用连续内存之外,MATLAB必须生成数组的副本,并将该副本设置为新值。在此操作期间,内存中有两个原始数组的副本。这将暂时使数组所需的内存量增加一倍,并增加程序在执行期间耗尽内存的风险。最好在一开始就为数组的最大潜在大小预先分配足够的内存。看到预先配置.
复制数组
在内部,多个变量可以指向同一个数据块,从而共享该数组的值。当你将一个变量复制到另一个变量时(例如,B =一个
), MATLAB会复制数组引用,但不会复制数组本身。只要不修改数组的内容,就不需要存储它的多个副本。如果修改数组的任何元素,MATLAB会生成数组的副本,然后修改该副本。
此示例使用内存
函数演示MATLAB如何处理数组复制。内存
只在Windows上可用®系统。
首先创建一个简单的脚本memUsed.m
显示您的MATLAB进程正在使用多少内存。将这两行代码放入脚本中。
[usr, sys] =内存;usr。MemUsedMATLAB
获取你的MATLAB进程正在使用多少内存的初始读数:
格式短eng;memUsed ans = 295.4977e+006
创建一个2000 × 2000的数字数组a,这将使用大约32MB的内存:
一个=魔法(2000);memUsed ans = 327.6349e+006
复制一个数组一个
在B
.由于不需要数组数据的两个副本,MATLAB只生成数组引用的一个副本。这并不需要额外的内存:
B =一个;memUsed ans = 327.6349e+006
现在修改B
将其大小设为原来的一半(也就是说,将1000行设为空)。这要求MATLAB至少复制前1000行一个
数组,并将该副本赋值给B
:
: B (1001:2000) = [];格式短;size(B) ans = 1000
再次检查内存使用情况。尽管B
明显比原来小,MATLAB进程使用的内存量增加了约16 MB(原来需要32 MB的1/2一个
),因为B
不能再仅仅作为参考一个
:
格式短eng;memUsed ans = 343.6421e+006
数组头
当你将一个数组赋值给一个变量时,MATLAB还会将关于数组的信息(比如类和维度)存储在一个叫做头文件的单独内存中。对于大多数数组,存储头文件所需的内存是微不足道的。将大数据集存储在少量的大数组中与存储在大量的小数组中相比有一个小小的优势。这是因为前一种配置需要更少的数组标头。
结构和单元格数组。对于结构和单元格数组,MATLAB不仅为每个数组创建头文件,而且为结构的每个字段和单元格数组的每个单元格创建头文件。正因为如此,存储结构或单元格数组所需的内存量不仅取决于它所容纳的数据量,还取决于它的构造方式。
例如,以一个标量结构数组为例S1
在字段R
,G
,B
.每个大小为100 × 50的字段都需要一个数组报头来描述整体结构,每个惟一的字段名需要一个报头,对于1 × 1的结构数组,每个字段需要一个报头。这使得整个数据结构总共有7个数组头:
S1.R (1:10 0, 1:50) S1.G (1:10 0, 1:50) S1.B (1:10 0, 1:50)
另一方面,以一个100 × 50的结构数组为例S2
其中每个元素都有标量字段R
,G
,B
.在这种情况下,你需要一个数组头来描述整个结构,每个唯一的字段名对应一个数组头,结构的5000个元素中每个字段对应一个数组头,这样整个数据结构总共有15,004个数组头:
S2(1:10 0, 1:50)。RS2(1:10 0, 1:50)。GS2(1:10 0, 1:50)。B
尽管S1
而且S2
包含相同数量的数据,S1
使用的内存空间明显减少。不仅需要更少的内存,而且使用S1
格式。
参见下面的“单元格阵列”和“结构”数据结构与内存.
whos函数报告的内存使用情况。的谁
函数显示任何变量所消耗的内存量。为了简单起见,谁
只报告用于存储实际数据的内存。例如,它不报告数组头的存储空间。
函数参数
MATLAB以类似的方式处理函数调用中传递的参数。当您将变量传递给函数时,实际上是传递了对该变量所代表的数据的引用。只要输入数据没有被调用的函数修改,调用函数中的变量和被调用函数中的变量都指向内存中的相同位置。如果被调用的函数修改了输入数据的值,那么MATLAB会在内存的新位置生成原始数组的副本,用修改后的值更新该副本,并将被调用函数中的输入变量指向这个新数组。
在下面的例子中,函数myfun
修改传入数组的值。MATLAB在内存中复制by指向的数组一个
,设置变量X
作为这个新数组的引用,然后设置一行X
为零。引用的数组一个
保持不变:
一个=魔法(500);myfun(一个);函数myfun(X) X(400,:) = 0;
如果调用函数需要它传递给的数组的修改值myfun
,您需要返回更新后的数组作为被调用函数的输出,如这里for variable所示一个
:
一个=魔法(500);一个= myfun (A);sprintf(' A的新值是%d', A)函数Y = myfun(X) X(400,:) = 0;Y = X;
数据结构与内存
不同类型的MATLAB数据结构对内存的要求不同。通过考虑MATLAB如何存储这些结构,您可能能够减少用于这些结构的内存量。
数字数组
MATLAB分别需要1、2、4或8字节来存储8位、16位、32位和64位的有符号和无符号整数。对于浮点数,MATLAB使用4或8字节单
而且双
类型。在处理数字数组时,为了节省内存,MathWorks . xml®建议使用包含数据且不溢出的最小整数或浮点类型。有关更多信息,请参见数值类型.
复杂的数组
MATLAB将复杂数据存储为独立的实部和虚部。如果复制一个复杂数组变量,然后只修改数组的实部或虚部,MATLAB会创建一个同时包含实部和虚部的数组。
稀疏矩阵
最好在稀疏格式中存储矩阵的值大多为零。稀疏矩阵可以使用更少的内存,也可能比完整矩阵操作更快。方法可以将完整矩阵转换为稀疏格式稀疏的
函数。
比较两个1000 × 1000矩阵:X
,一个双精度矩阵,其中2/3的元素为零;而且Y
,一个稀疏的副本X
.下面的例子显示稀疏矩阵大约需要一半的内存:
whos名称大小字节类X 1000x1000 8000000双数组Y 1000x1000 4004000双数组(稀疏)
细胞数组
除了数据存储外,单元阵列还需要一定数量的额外内存来存储描述每个单元的信息。该信息记录在头,数组的每个单元格都有一个标头。你可以通过查找不包含数据的1 × 1单元格所消耗的字节数来确定单元格数组头所需的内存量,如下图所示的32位系统:
一个= {[]};空单元格数组,名称大小字节类属性1x1 60单元格
在这种情况下,MATLAB显示在32位系统上单元格数组中每个头所需的字节数为60。这是本节中所有32位示例中使用的头大小。对于64位系统,本文档假设头大小为112字节。您可以在64位系统上使用刚才为32位所展示的方法找到正确的报头大小。
要预测整个单元格数组的大小,请将您为头文件导出的数字乘以数组中单元格的总数,然后将您打算存储在数组中的数据所需的字节数相加:
(header_size x number_of_cells) +数据
因此,一个包含400字节数据的10 × 20单元格数组在64位系统上需要22800字节的内存:
(112 x 200) + 400 = 22800
请注意
数值数组必须存储在连续的内存中,而结构和单元格数组则不需要。
例1 -单元格数组的内存分配。下面的4 × 1单元阵列记录了三种笔记本电脑的品牌名称、屏幕尺寸、价格和销售状态:
笔记本电脑= {['SuperrrFast 89X', 'ReliablePlus G5',…“哈佛UCanA4dIt 140”);...(单(17),单(15.4),单(14.1)];...(2499.99, 1199.99, 499.99);...(真的,真的,假的)};
在32位系统上,单是单元格数组头就需要每个单元格60字节:
对于单元格数组,每个单元格* 60字节= 240字节
计算在四个单元格中包含数据所需的内存:
45字符* 2字节每字符= 90字节3双字节* 8字节每双字节= 24字节3单字节* 4字节每单字节= 12字节3逻辑* 1字节每逻辑= 3字节90 + 24 + 12 + 3 = 129字节的数据
将两者相加,然后将结果与MATLAB返回的大小进行比较:
240 + 129 = 369字节总计whos笔记本电脑名称大小字节类属性笔记本电脑4x1 369 cell
结构
s.a. = [];B =谁(“S”);B.bytes - 60 ans = 64
计算一个结构数组所需的内存如下:
32位系统:字段x((60个数组元素)+ 64)+数据64位系统:字段x((112个数组元素)+ 64)+数据
在64位计算机系统中,4乘5的结构客户
与字段地址
而且电话
仅为结构使用4,608字节:
2个字段x (112 x 20) + 64) = 2 x(2240 + 64) = 4608字节
在这个总和上,必须加上存储分配给每个字段的数据所需的内存。如果将25个字符的向量赋值给地址
和一个12个字符的向量电话
在4 × 5矩阵的每个元素中客户
数组,你使用1480字节的数据:
(25+12)个字符* 2个字节每个字符* 20个元素= 1480字节
将两者相加,您会看到整个结构消耗6088字节的内存。
例1 -结构数组的内存分配。计算在32位系统上存储具有以下四个字段的6 × 5结构数组所需的内存量:
A: 5 × 8 × 6有符号8位整数数组B: 1 × 500单数组C: 30 × 30无符号16位整数数组D: 1 × 27字符数组
构建数组:
一个= int8((5、8、6));B =单(1:50 0);C = uint16(魔法(30));D = '公司名称:MathWorks';s = struct('f1', A, 'f2', B, 'f3', C, 'f4', D);n=1:5 s(m,n)=s(1,1);结束结束
计算结构本身所需的内存量,然后计算它包含的数据:
Structure = fields x ((60 x array elements) + 64) = 4 x ((60 x 30) + 64) = 7,456 bytes data = (field1 + field2 + field3 + field4) x array elements = (240 + 2000 + 1800 + 54) x 30 = 122,820 bytes
将两者相加,然后将结果与MATLAB返回的大小进行比较:
结构s计算的总字节数:7,456 + 122,820 = 130,276 whoos s名称大小字节类属性s 6x5 130036结构s