Verfasst am: 27.09.2010, 16:01
Titel: 20 MB+ große Tabellen laden
Hi Leute, habe mal ne kleine theoretische Frage =)
Könnte mir jemand sagen, welcher befehl sich am besten dafür eignet, sehr große ASCI-Tabellen zu laden?
Mit einem Script was ich da hab geht das leider viel zu langsam, ab 18 MB ( ca 20 files) geht das auf über 10 Minuten.
Hab da diese Funktion, die mehrere Dateien lädt, klappte bis dahin auch ganz gut, aber jetzt, bei großen Dateien, dauerts einfach zu lange:
Code:
function[M] = fc(a,b,c,d,e,f,pfad) % Function to load any amount of files of target direction % with the name like: phs0a-b_000c-d_0000e-f
% Using the variables of the function to define the file name % fix and mod are used to round the variables c and d, so if u use % Numbers from 1 to 9, they're written as 01 -09
% defining list as the direction u've chosen by typing the variables in Octave-command-window
list=dir([pfad,'\*']);
% defining names as a combination of list and names
names={list.name};
% regexp is used to check names with the string above and save all the matched ones in X
X=regexp(names,string,'match');
% returns the indicies of the empty cells.
ind=cellfun('isempty',X);
% ~means "not", or in our case "without" % so X now stands for all the files, which could be identified through our function(insert)
X=X(~ind); % delete the empty cells % in this case the number of the files identified.
len=length(X);
% for-loop to read all the files defined through the function-insert % in reads all the files which matched through regexp and identified by cellfun tic for ii=1:len
% due to an unknown reason, it returns the files with an additional 0-vector as first, this is needet to delete it Cell{ii}(:,1)=[];
% all the matrices are saved in workspace one by one,(in a cell), this is needet to bring em all in one matrix(double)
M = cell2mat(Cell');
end;
C = cell(1, len); % Pre-allocate !!!!!!! for ii=1:len
Data =dlmread(fullfile(pfad, X{ii})); % CHAR überflüssig?!
C{ii} = Data(:, 2:end);
M = cell2mat(C'); % Wozu ist das gut? Habe ich nicht verstanden end
Es ist sehr wirchtig, wachsende Arrays immer vor der Schleife mit der vollen Länge zu definieren. Wenn in jeder Schleife neuer Speicher angefordert wird, kann das dramatisch langsam sein.
Wandelst Du die CELL in jedem Durchlauf per CELL2MAT in eine Matrix? Müsste das nicht einmal am Ende reichen?
Ich würde die CELL übrigens nicht "Cell" nennen, aber es ist auch kein Fehler.
Was sagt denn der Profiler, wo die meiste Zeit gebraucht wird?
Hallo!
Danke für deine schnelle und konstruktive Antwort.
Mein Code sieht jetzt so aus, angepasst:
Code:
function[M] = fc(a,b,c,d,e,f,pfad) % Function to load any amount of files of target direction % with the name like: phs0a-b_000c-d_0000e-f
% Using the variables of the function to define the file name % fix and mod are used to round the variables c and d, so if u use % Numbers from 1 to 9, they're written as 01 -09 tic
string = sprintf('phs0[%d-%d]_000[%d-%d][%d-%d]_0000[%d-%d]',...
a,b,fix(c/10),fix(d/10),mod(c,10),mod(d,10),e,f) ;
% defining list as the direction u've chosen by typing the variables in Octave-command-window
list=dir([pfad,'\*']);
% defining names as a combination of list and names
names={list.name};
% regexp is used to check names with the string above and save all the matched ones in X
X=regexp(names,string,'match');
% returns the indicies of the empty cells.
ind=cellfun('isempty',X);
% ~means "not", or in our case "without" % so X now stands for all the files, which could be identified through our function(insert)
X=X(~ind); % delete the empty cells % in this case the number of the files identified.
len=length(X);
% for-loop to read all the files defined through the function-insert % in reads all the files which matched through regexp and identified by cellfun
C = cell(1, len);
for ii=1:len
Data = dlmread(fullfile(pfad,char(X{ii})));
C{ii} = Data(:, 2:end);
endfor;
% all the matrices are saved in workspace one by one,(in a cell), this is needet to bring em all in one matrix(double)
M = cell2mat(C');
end;
Aber es ist leider immernoch dramatisch langsam..
Die meiste Zeit geht in der For-Schleife weg.
Die Zeit steigt unproportional, also viel stärker an, bei Zunahme der Datengröße.
Also bei 1 MB dauerts z.B. 9 Sekunden, bei 2MB 40 und bei 15MB 2430 Sekunden.
Ich versteh das einfach nicht, bitte dringend um Hilfe )
Mfg
paet0r
Wird bei "char(X{ii})" das "char" wirklich benötigt?
Wird CELL2MAT innerhalb der FOR-Schleife aufgerufen? Die Funktion ist nicht sehr effizient, weil offenbar das Pre-allocieren vergessen wurde. Ich komme leider nicht dazu mein "CELL2VEC" in der FEX zu veröffentlichen - ein blöder Nachteil des 24-Stunden-Tages.
Bringt es etwas DLMREAD mit dem Range-Argument aufzurufen, statt zunächst alles zu lesen und dann später das überflüssig wieder wegzuwerfen?
muss da hin, da die Funktion am sonsten leider nicht funktioniert.
Nein, cell2mat braucht natürlich nicht in der for-schleife aufzutauchen.
Das ist aber auch nicht die STelle, an der die meiste Zeit verbraucht wird. Alle Datenbearbeitungs-Befehle gehen eigentlich relativ schnell, nur bei der for-Schleife dauerts auf einmal ewig. Kann mir einfach nicht erklären, warum das auf einmal so exponentiell viel langsamer wird.
Das hier:
Zitat:
Bringt es etwas DLMREAD mit dem Range-Argument aufzurufen, statt zunächst alles zu lesen und dann später das überflüssig wieder wegzuwerfen?
Habe ich leider nicht ganz verstanden, was meinst du damit? Hab zwar ein wenig Ahnung mittlerweile, aber perfekt auskennen mit Matlab tuh ich mich noch nicht =)
Was meinst du mit dem Pre-allociieren, und wie krieg ich das hin? =)
Danke nochmal für deine Hilfe.
Hier drinnen befindet sich also Dein eigentliches Problem.
DLMREAD mit einem Range aufzurufen (siehe "help dlmread") bringt nicht viel: ich habe den Source von DLM durchgesehen und dort passiert genau das gleiche wie bei Data(:, 2:end).
Dort fand ich aber ein paar Ansätze für eine Beschleunigung:
1. Wenn DLMREAD aufgerufen wird ohne den Delimiter zu definieren, liest es probeweise 4096 Zeichen ein und versucht den Delimiter zu erraten. Das kosten natürlich Zeit. Wenn Du den Delimiter kennst, gibt ihn als Input für DLMREAD ein.
2. DLMREAD ruft eigentlich nur TEXTSCAN auf. Das könntest Du auch direkt machen und den Overhead sparen.
Zum Pre-allocieren kannst Du ja einfach mal in diesem Forum suchen. Leider weiss wohl keiner so genau, wie man das buchstabiert... Preallocate, preallocation, Preallozieren, etc. Sich damit auszukennen ist sehr wichtig, wenn man in Matlab effiziente Programmem schreiben möchte.
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.