我发现sclarke81和Sam Robert的回答实际上都不起作用,而且我怀疑预分配的概念是否适用于
matfile
。下面报告的结果是在i7-3770 CPU @ 3.4 GHz、16.8 GB主存储器上运行Matlab R2013a,Linux 3.16系统下获得的。
代码:
mf = matfile(fn, 'Writable', true);
mf.x(5000, 200000) = 0;
clear mf
理论上,此代码在磁盘上“分配”了8 GB的内存,并初始化为0。然而,生成的文件大小只有4726字节,整个过程不到0.01秒。我可以将大小增加10倍或100倍,但并没有太大变化。很奇怪。顺便说一句,结尾处的
clear
是为了确保Matlab写入和关闭文件。
通常,我们希望预分配时将NaN初始化而不是0。用这种方法接收更好。
mf = matfile(fn, 'Writable', true);
mf.x = nan(5000, 200000);
clear mf
该方法需要11秒钟,并生成57 MB的文件。但正如OP所指出的,这种方法没有意义,因为它首先在内存中生成整个8 GB矩阵,然后再将其写出,这违背了
matfile
的目的。如果矩阵可以放入内存,则在处理数据时没有理由将数据保留在文件中。
Sam Roberts建议首先分配/初始化为0,然后将值更改为NaN:
mf = matfile(fn, 'Writable', true);
mf.x(5000, 200000) = 0;
mf.x = mf.x * nan;
clear mf
这需要16秒,生成的文件大小相同。然而,这种方法并不比上面的朴素方法更好,因为在第三行中,整个矩阵被读入内存,与标量NaN在内存中相乘,然后再次写出,导致峰值内存消耗为8GB。(这不仅符合
文档中解释的
matfile
变量的语义,我还使用了内存使用监视器进行了检查。)
sclarke81提议通过以下方式避免在内存中生成矩阵:
mf = matfile(fn, 'Writable', true);
mf.x(1 : 5000, 1 : 200000) = nan;
clear mf
这个想法可能是只在内存中生成一个标量NaN,然后将其复制到磁盘矩阵的每个元素中。然而,事实并非如此。实际上,这种方法似乎会在峰值时消耗约8.38 GB的内存,比朴素方法多出12%!
现在更多地谈论使用
matfile
进行预分配的优点。如果不进行预分配,但是按行用NaN填充数组。
mf = matfile(fn, 'Writable', true);
for i = 1 : 5000
mf.x(i, 1 : 200000) = nan(1, 200000);
end
clear mf
这需要27秒。但是,如果预先分配并初始化为0,然后逐行用NaN进行覆盖。
mf = matfile(fn, 'Writable', true);
mf.x(5000, 200000) = 0;
for i = 1 : 5000
mf.x(i, 1 : 200000) = nan(1, 200000);
end
clear mf
它需要很长时间:当我在45分钟后中止进程时,进程仅完成约3%,推算总运行时间大约为一天!
matlab.io.MatFile
的行为是黑暗而神秘的,目前似乎只有广泛测试才能找到有效使用此功能的方法。然而,人们可以得出结论,在处理
matfile
时,预分配是一个不好的想法。