MATLAB:访问已加载的MAT文件非常缓慢

3

我目前正在处理一个涉及保存/加载相当大的MAT文件(约150 MB)的项目,并且我意识到,访问已加载的单元数组比在脚本或函数内创建的等效版本要慢得多。

我创建了这个示例来模拟我的代码并展示差异:

clear; clc;

disp('Test for computing with loading');

if exist('data.mat', 'file')
    delete('data.mat');
end

n_tests = 10000;
data = {};
for i=1:n_tests
    data{end+1} = rand(1, 4096);
end

% disp('Saving data');
% save('data.mat', 'data');
% clear('data');
% 
% disp('Loading data');
% load('data.mat', '-mat');

for i=1:n_tests
    tic;
    for j=1:n_tests
        d = sum((data{i} - data{j}) .^ 2);
    end
    time = toc;
    disp(['#' num2str(i) ' computed in ' num2str(time) ' s']);
end

在这段代码中,没有保存或加载MAT文件。对于循环i的一个迭代平均时间为0.75秒。当我取消注释保存/加载文件的行时,对于循环i的一个迭代计算需要大约6.2秒(不考虑保存/加载时间)。这是8倍的差距!
我正在使用MATLAB 7.12.0(R2011a)64位和Windows 7 64位,MAT文件以版本v7.3保存。
这可能与MAT文件的压缩有关吗?或者缓存变量?
有没有一种方法可以防止/避免这种情况?

你使用单元格而不是矩阵,有重要的原因吗? - cyborg
实际上,与保存/加载矩阵相比,使用或不使用矩阵的差异要小于使用或不使用单元数组,但问题仍然存在:对于10000个测试,计算矩阵(10000行)需要4.3秒,而不使用矩阵只需要1.5秒;使用单元数组(10000个元素)需要6.1秒,而不使用单元数组只需要0.4秒。 - Ben B.
2个回答

5
我也知道这个问题。我认为这也与matlab中内存管理的低效有关 - 而且据我记得,它在交换方面表现不佳。 一个150MB的文件可以轻松地容纳大量数据 - 可能比快速分配的数据还要多。
我刚刚使用mathworks提供的信息对你的示例进行了快速计算。 在你的情况下,total_size = n_tests*121 + n_tests*(1*4096*8)大约是313MB。
首先,我建议将它们保存在格式7中(而不是7.3) - 我注意到读取这种新格式的性能非常差。这可能是你减速的原因。
就我个人而言,我用两种方法解决了这个问题:
  1. 将数据分成较小的集合,然后使用在需要时加载数据或在运行时创建数据的函数(可以通过类来优雅地完成)
  2. 将数据移入数据库。SQLite和MySQL都很好。两者都可以有效地处理比GB级别更大的数据集(达到TB级别)。并且SQL语言非常高效,可以快速获取子集以进行操作。

大小确实约为300 MB ... 但是MATLAB 64位应该很容易管理,不是吗?我将格式从7.3更改为7,现在没有减速了,性能与保存或不保存相同!将来我会看看SQL,因为数据可能比这个大得多。最终,单元数组和矩阵之间仍然存在差异(前者更快)。这是否与矩阵的大小及其内存管理有关?无论如何,非常感谢您的提示! - Ben B.
+1 同意,我个人使用 MS SQL Server Express,它附带了一个不错的免费管理工具 - 如果你是新手,这很有用。至于连接到数据库,我建议使用这个库 http://www.mathworks.com/matlabcentral/fileexchange/29615-adodbtools 而不是内置的 Matlab 库。 - James

-1

我在Windows 64位系统下,使用Matlab 2014b 64位测试了这段代码。

如果不进行保存和加载,计算时间大约为0.22秒, 使用“-v7”选项保存数据文件并加载后,计算时间大约为0.2秒。 使用“-v7.3”选项保存数据文件并加载后,计算时间大约为4.1秒。 因此,这与MAT文件的压缩有关。


请尝试回答所提出的问题并解决所遇到的问题。 - Lupin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接