【问题标题】:Why does my matlab program use so much memory?为什么我的 matlab 程序使用这么多内存?
【发布时间】:2016-02-20 16:59:04
【问题描述】:

我正在编写一个 matlab 程序,它可以读取大约 500 个文件。每个文件有 20,000 行,每行有 1 个数字。该程序试图用这些数字构建一个 20,000 * 500 的矩阵。 这些数字存储为 Double,因此每个数字 8 个字节。所以我预计这需要 20,000 * 500 * 8 字节,大约是 1E8,即 100MB。然而这个程序耗尽了我的 16GB 内存。当程序运行时,我看到内存使用量稳步上升,每 GB 增加 GB。我在 Ubuntu 14.04 上使用 Matlab R2015b。

发生了什么事?非常感谢您的关注。

这是完整的代码

clear all;
% number of rna bits in the file
filesize = 20532

maxFiles = 480;
rnaCounts = NaN(filesize,maxFiles);

myFolder = '~/_STATS/data3/RNASeqV2/UNC__IlluminaHiSeq_RNASeqV2/Level_3';
filePattern = fullfile(myFolder, '*genes.normalized_results');

theFiles = dir(filePattern);

rnaCounts = NaN(filesize,length(theFiles));


for k = 1 : length(theFiles) 
    mrnaFilename = strtrim(theFiles(k).name);
    fprintf(1, 'Now reading mrnaFile %d %s  \n', k, mrnaFilename);

    % read rna file
    fullFileName = fullfile(myFolder, mrnaFilename);
    rnafid = fopen(fullFileName);

    if rnafid < 0 
       fprintf('====ERROR OPENING RNA FILE =====================');
    end
    rnaline = fgets(rnafid);

    lc = 1;  % line counter
    while ischar(rnaline) && feof(rnafid) ~= 1
       rnaline = fgets(rnafid);
       rnaSplit = strsplit(rnaline);

       % write to the matrix
       rnaCounts(lc,k) = str2num(rnaSplit{2});

       lc = lc + 1;
    end
    fclose(rnafid);

end

【问题讨论】:

  • 尝试删除rnaCounts的第一个实例;它未被使用且非常大,但这不应该是导致内存爆炸的原因。
  • 另外,尝试str2double 而不是str2num。这不完全是str2num 的用途。 help str2numhelp str2double
  • 你确定内存被 Matlab 持有,而不仅仅是文件系统缓存吗?例如如果你杀了Matlab,所有的内存会立即清除吗?
  • @old_Mortality:您可以将当前数据存储在*.mat 文件中,并为每次迭代重新加载。在每次迭代之间使用clear all希望释放一些内存。不是很优雅,但它可能会起作用
  • 非常感谢您的所有建议。 @drhagen 用 strdouble() 替换 strnum() 的想法解决了这个问题。所以我现在了解到 strnum() 对矩阵进行操作,而 strdouble() 应该用于单个字符串。 strnum() 的一个意想不到的副作用!

标签: matlab memory


【解决方案1】:

经 OP 验证,Linux 版 Matlab 2015b 中的str2num 函数存在内存泄漏。无论如何,此函数并不是很有用,因为它旨在解析表示整个矩阵的字符串 (1 2; 3 4),而不是解析单个数字 (1.234) 的典型用例。做简单数字解析时使用str2double;即使str2num 没有损坏,它也更快。

使用不同版本的 Matlab 也可能会解决该问题,因为根据我的经验,这些类型的内存错误通常不会从一个版本持续到下一个版本。

【讨论】:

    【解决方案2】:

    通常,高级 I/O 函数(例如 dlmreadtextscan)对于读取此类文本格式很有用。如果您只有 numeric 数据,请使用 dlmread, 和textscan 用于更复杂的格式。

    您提供的样本数据是:

    A2LD1|87769 135.5735

    由于您只需要第二列的数字,而丢弃第一列的标识符,所以您只有数字数据,您可以使用dlmread

    data = dlmread(fullFileName, '\t', 1, 1);
    

    \t 是指定分隔符(列分隔符)为制表符。两个1s是指定行偏移和列偏移,即忽略文件的第一行(标题)和第一列(id)。

    【讨论】:

    • 谢谢,我会试试的。
    猜你喜欢
    • 1970-01-01
    • 2015-05-13
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    相关资源
    最近更新 更多