【问题标题】:Reading external files more efficiently in MATLAB在 MATLAB 中更有效地读取外部文件
【发布时间】:2014-01-30 16:58:25
【问题描述】:

我有以下问题,我开发了一个代码来搜索包含数据的大文件,这个过程变得太慢了,甚至在某些计算机上它消耗了所有可用的计算机资源。

nodo=str2num(get(handles.nodo,'string'));                                 
PATHNAME = uigetdir('', 'Selecciona el directorio donde están los bfins');
files = dir(fullfile(PATHNAME,'*.bfin') );                                
curr_folder=pwd;                                                          
cd(PATHNAME);                                                             
archivo={files.name}';                                                    
for i=1:numel(archivo)                                                    
        [fid{i}, errmsg]=fopen(files(i).name)                                 
        disp(errmsg);                                                         
        Datos{i}=textscan(fid{i}, '%s  %f %s %f %s %f ','Headerlines',2);     
        AllNodos{i}=Datos{1,i}{1,2};                                          
        AllTemp{i}=Datos{1,i}{1,4};                                           
end                                                                       
cd(curr_folder)                                                           
for i=1:size(AllNodos,2)                                                  
        sets{i}=cat(2, AllNodos{1,i}, AllTemp{1,i});                          
end                                                                       
for i=1:size(AllNodos,2)                                                  
        vectn{i}=AllNodos{1,i};                                               
        r{i}=find(vectn{i}==nodo);                                            
        Temps{i}=AllTemp{1,i}(r{i});                                          
end  
    %Write Excel File
[FileName, PathName] = uiputfile('*.xlsx', 'Escribe un archivo excel con las    temperaturas...')
savingas=fullfile(PathName,FileName);
a=archivo';
B=cat(1,a,Temps); 
xlswrite(savingas,[B])
e = actxserver ('Excel.Application'); %# open Activex server
ewb = e.Workbooks.Open(savingas); %# open file (enter full path!)
ewb.Worksheets.Item(1).Name = num2str(nodo); %# rename 1st sheet
ewb.Save %# save to the same file
ewb.Close(false)
e.Quit                                                              

代码的真正作用是在文件中找到一个字符串的位置,然后找到另一个变量(只是一个 cntrl+f 操作)并在 Excel 表中重现它们,任何有关此的帮助将不胜感激。

编辑---- 非常感谢你们所有的 cmets,我想出了以下代码,它通过存储变量节省了大量不必要的时间:

    for i=1:num_archivo
   [fid(i), errmsg]=fopen(files(i).name)
   disp(errmsg);
   Datos=textscan(fid(i), '%s  %f %s %f','delimiter',',','HeaderLines',hl);
   AllNodos=Datos(1,2);
   AllTemp=Datos(1,4);
   for k=1:numel(nodo)
    r{i,k}=find(AllNodos{1,1}==nodo(k));
    Temps{i,k}=AllTemp{1,1}(r{i,k});
   end
   end

【问题讨论】:

  • 文件有多大,大概是多少文件?
  • 每个文件大约 25Mb,大约需要处理 8 个文件

标签: matlab file batch-file external textscan


【解决方案1】:

textscan 本身非常快,因此它可能会占用 CPU,但您不太可能在性能方面对其进行改进。但是,您似乎没有为单元阵列执行任何类型的预分配。这意味着 Matlab 可能会不断地重新分配内存。使用cell 创建所需大小的空元胞数组:

num_archivo = numel(archivo);
Datos = cell(1,num_archivo);
AllNodos = cell(1,num_archivo);
AllTemp = cell(1,num_archivo);
for i = 1:num_archivo
    ...
end
...

(虽然Datos 可能不应该是@Lazarus 指出的单元格。)您应该对setsvectn 等其他循环执行相同的操作。

我一定要做的另一件事是在你读完files(i).name 后立即调用fclose(fid);,这样你就没有一堆打开的文件指针。此外,似乎没有理由将文件 id fid 保存到元胞数组中,因为您不在循环之外使用它。即使你这样做了,一个常规向量(分配有numel(archive) 元素)会更好。

【讨论】:

    【解决方案2】:

    我的答案取决于您的数据集有多大。但我要做的第一个更改是将Datos{i} 设置为Datos,因为您只在for 循环中使用它。这样matlab就不必分配更多空间了。

    我要做的第二个更改是在第一个 for 循环中包含 catfind 函数,这样您还可以将 Allnodos{i} 替换为 Allnodos 并节省分配问题。

    这应该有助于解决资源问题;如果 textscan 是限制因素,它可能无助于速度问题。在 textscan 前后使用 tictoc 会让您知道需要多长时间。

    【讨论】:

    • 您能否更具体地了解您的解决方案?,我尝试了您所说的,但我收到错误“索引超出矩阵尺寸”,感谢您的帮助。
    【解决方案3】:

    这取决于您的“大”文件实际有多大以及有多少。 使用分析器检查您的代码:

    profile on;
    <run your code>
    profile viewer
    

    我怀疑fopentextscan 行是邪恶的...

    通常在任何与读取文件有关的事情中,瓶颈主要是磁盘 i/o,而不是 CPU。 在那种情况下,除了并行做事之外,你真的不能做很多事情,不幸的是,这在 matlab 中并不容易——如果你不愿意付钱的话。

    【讨论】:

    • 能否详细说明并行操作,我怀疑你说的是并行计算机工具箱;我真的不在乎这个过程是否需要很多时间,但是当我运行这段代码时,我不能将我的计算机用于其他任务,有什么办法吗?
    • 是的 - 您可以使用并行代码使事情变得更快。但是,如果这个单一进程已经在减慢您/任何计算机的速度(或者只有一个 matlab 实例?),那么更多进程可能会使事情变得更糟......