1

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

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 表中重现它们,任何有关此的帮助将不胜感激。

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

    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
4

3 回答 3

1

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

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

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

于 2014-01-30T17:38:07.163 回答
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等等。

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

于 2014-01-30T18:22:23.967 回答
1

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

profile on;
<run your code>
profile viewer

我怀疑那fopentextscan线条是邪恶的......

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

于 2014-01-30T18:37:05.610 回答