我遇到以下问题,我开发了一个代码来搜索包含数据的大型文件,这个过程变得太慢,甚至在某些计算机中它会占用所有可用的计算机资源。
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表中重现它们,任何有关这方面的帮助都将受到赞赏。
EDIT ---- 非常感谢您的所有评论,我想出了以下代码,通过存储变量节省了大量不必要的时间:
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
答案 0 :(得分:1)
我的答案取决于数据集的大小。但我要做的第一个更改是将Datos{i}
设置为Datos
,因为您只在for循环中使用它。这样matlab就不必分配更多空间。
我要做的第二个更改是在第一个for循环中包含cat
和find
函数,这样您也可以将Allnodos{i}
替换为Allnodos
并节省分配问题。
这应该有助于资源问题;如果文本扫描是限制因素,它可能无助于速度问题。在文本扫描之前和之后使用tic
和toc
会告诉您它需要多长时间。
答案 1 :(得分: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指出的单元格。)你应该对sets
,vectn
等其他循环做同样的事情。
我确定要做的另一件事是在您阅读files(i).name
之后立即调用fclose(fid);
,这样您就没有一堆打开的文件指针。此外,似乎没有理由将文件ID fid
保存到单元阵列,因为您不在循环外使用它。即使你这样做,常规向量(用numel(archive)
元素分配)也会更好。
答案 2 :(得分:1)
这取决于“大”文件的实际大小和数量。 使用探查器检查您的代码:
profile on;
<run your code>
profile viewer
我怀疑fopen
和textscan
行是邪恶的......
一般来说,在阅读文件的任何事情上,瓶颈主要是磁盘i / o - 而不是CPU。 在这种情况下,除了并行处理之外你不能真正做很多事情,不幸的是在matlab中并不那么容易 - 如果你不愿意支付。