WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Performance Probleme beim Einlesen von ASCII Datei

 

Innoopia
Forum-Newbie

Forum-Newbie


Beiträge: 5
Anmeldedatum: 12.10.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.08.2012, 18:49     Titel: Performance Probleme beim Einlesen von ASCII Datei
  Antworten mit Zitat      
Hallo zusammen,

ich lese schon eine Weile mit und habe viele Matlab Probleme damit gelöst, aber jetzt stoße ich an meine Grenzen. Bin allerdings auch nicht so in der Materie, außerdem "fachfremd" Very Happy

Die einzulesende Datei ist etwas kompliziert. Sie ist folgendermaßen aufgebaut:

Header
Header
Header
[Zahl1]
+1.35433E+05+0.34543E-01-1.34533E+05
+1.76433E+05-0.36743E-01+1.39833E+05
...
Header
Header
[Zahl2]
34 24 46 78 89 90 90 78
18 27 54 23 54 90 09 18
...

---------------------------------------------------

Wie ihr sehen könnt, hat die Datei bei dem ersten Zahlenblock KEINE Leerzeichen dazwischen, aber immer 12 Zeichen Länge. Der zweite Zahlenblock ist mit Tabs getrennt. Achso und die Datenmenge ist riesig.
Gelöst (und es funktioniert auch) habe ich es so:

Code:

% File importieren
fid = fopen(fullfile(PathName,FileName));

%Header lesen
for n=1:6
    header{n,1} = fgets(fid);
end

%Punkte einlesen
i=1;
tline=header{6,1};
while ischar(tline)
    tline = fgets(fid);
    node{i,1}=tline(1:12);
    node{i,2}=tline(13:24);
    node{i,3}=tline(25:37);
    i=i+1;
    if i==str2double(header{6,1})+1
        break
    end
end

% zweiten Header einlesen
for m=1:4
    header2{m,1} = fgets(fid);
end

cell=NaN(str2double(header2{4,1}),8);

% Zellen einlesen
for l=1:str2double(header2{4,1})
    tline = textscan(fgets(fid), '%n%n%n%n%n%n%n%n', 'delimiter', '\t');
    cell(l,1)=tline{1};
    cell(l,2)=tline{2};
    cell(l,3)=tline{3};
    cell(l,4)=tline{4};
    cell(l,5)=tline{5};
    cell(l,6)=tline{6};
    cell(l,7)=tline{7};
    cell(l,8)=tline{8};
end

fclose(fid);
 


Zahl1, bzw Zahl2 geben eben an, wieviel Zeilen von Cell, bzw Node in der Originaldatei stehen. Als Ergebnis sollen einfach zwei Matrizen (Cell und Node) erstellt werden mit allen Werten.
Das tut mein Code auch ohne Probleme, aber durch das zeilenweise Einlesen gerate ich in dermaßene Performance Probleme, dass der Code eigentlich unbrauchbar ist. Es benötigt ca 3-4 Minuten pro Datei und ich muss mindestens 40 Stück einlesen.

Hat jemand eine Idee zum besser machen?

Danke,
Christoph
Private Nachricht senden Benutzer-Profile anzeigen


Sirius3
Forum-Guru

Forum-Guru


Beiträge: 441
Anmeldedatum: 12.11.11
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 29.08.2012, 22:32     Titel:
  Antworten mit Zitat      
Hallo Innoopia,

zuerst ein paar allgemeine Bemerkungen:
1) cell ist eine häufig genutzte Matlabfunktion um cell-Arrays zu erzeugen und sollte nicht als Variablenname benutzt werden.
2) das Erzeugen von einzelnen Cell-Strings in der ersten while-Schleife ist sehr langsam.
da es sich um Zahlen handelt, wäre es besser, die Strings gleich umzuwandeln und das
Ergebnis in einer Matrix zu speichern.
3) fgets ist aus irgendeinem Grund lahm.

Hier die schnellen Varianten:
Code:
fl=fopen(filename);
content=fread(fl,inf,'*char')';
fclose(fl);
[numbers, headers]=regexp(content,'(\n\s*[-+0-9.Ee \t]{20,}\s*\n)','match','split');
node = regexprep(numbers{1},'([+-]\d\.)',' $1'); % Leerzeichen einfuegen
node = reshape(sscanf(node,'%f'),3,[])';  % umwandeln in Zahlen
cells = reshape(sscanf(numbers{2},'%i'),8,[])';
 


Hoffe die Trennung in Zahlenblöcke und Header funktioniert so.

Grüße
Sirius
Private Nachricht senden Benutzer-Profile anzeigen
 
Innoopia
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 5
Anmeldedatum: 12.10.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 30.08.2012, 16:56     Titel:
  Antworten mit Zitat      
erstmal danke für deine Antwort Smile

leider hat es aber nicht ganz zum Erfolg geführt. Ich hab das Skript einmal nicht verstanden und außerdem glaube ich nicht dass die Trennung in header und numbers funktioniert hat.

Ich wollte nochmal sagen, dass die beiden Header unterschiedlich viele Zeilen haben können. Außerdem geht die Originaldatei auch noch weiter nach den ersten beiden Zahlenblöcken. Den restlichen Inhalt benötige ich allerdings nicht.

Gruß,
Christoph
Private Nachricht senden Benutzer-Profile anzeigen
 
Sirius3
Forum-Guru

Forum-Guru


Beiträge: 441
Anmeldedatum: 12.11.11
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 31.08.2012, 19:04     Titel:
  Antworten mit Zitat      
Hallo,

zur Erklärung: die ersten drei Zeilen lesen einfach die komplette Datei ein.
Dann wird der Inhalt über einen regulären Ausdruck in Blöcke aufgeteilt.
Ein Zahlenblock besteht aus Zeilen die nur Ziffern, +,-,E und Leerzeichen
enthalten und mindestens 20 Zeichen lang sind. Ich hoffe mal das diese
Bedingung eine Headerzeile nie erfüllt. Falls doch, muß man den regulären
Ausdruck komplizierter schreiben. Die letzten beiden Zeilen wandeln die
Blöcke am Stück in Zahlen um. Das geht viel viel schneller als einzeln.
Hier der leicht korrigierte Code:
Code:
fl=fopen(filename);
content=fread(fl,inf,'*char')';
fclose(fl);
[numbers, headers]=regexp(content,'\n([-+0-9.Ee \t]{20,}\s*\n)+','match','split');
node = regexprep(numbers{1},'([+-]\d\.)',' $1'); % Leerzeichen einfuegen
node = reshape(sscanf(node,'%f'),3,[])';  % umwandeln in Zahlen
cells = reshape(sscanf(numbers{2},'%i'),8,[])';


Grüße
Sirius
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 01.09.2012, 13:15     Titel:
  Antworten mit Zitat      
Hallo Innoopia,

Statt TEXTSCAN zeilenweise anzuwenden, kann du auch FID als inpuit benutzen und das File direkt einlesen. Da der Daten-Teil aber sehr einfach strukturiert ist, sollte dies auch ainfacher möglich sein:

Code:
% Zellen einlesen
n = sscanf(header2{4,1}, '%d');
C = fscanf(fid, '%d\t', [n, 8]);

Allerdings wundere ich mich über die 3-4 Minuten Rechenzeit. Das zeilenweise Einlesen ist im Allgemeinen nicht ineffizient. Denn das Betriebssystem puffert das File sowieso blockweise im RAM. TEXTSCAN ist weniger effizient als das einfachere FSCANF, aber wahnsinnig langsam ist es eigentlich nicht.
Möglicherweise hilft Dir der Profiler herauszufinden, was an Deinem Programm eigentlich so lange dauert. Liegt das File auf einem Netzwerklaufwerk?

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Innoopia
Themenstarter

Forum-Newbie

Forum-Newbie


Beiträge: 5
Anmeldedatum: 12.10.09
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.09.2012, 18:03     Titel:
  Antworten mit Zitat      
So hallo,

ich wollte euch nicht in Unkenntnis lassen Wink

Erstmal vielen Dank Sirius, der Code liest die Datei tatsächlich ein, auch in einer brauchbaren Geschwindigkeit.

Zur Frage mit dem Netzlaufwerk: Nein, alle Dateien waren lokal abgespeichert. Trotzdem sehr langsam. Was mich allerdings verwundert, ich habe meinen (alten) Code auf meinem Macbook Pro mit Matlab 2012 laufen lassen und es war VIEL schneller als auf dem Windows Rechner. Über die Performance des neuen Codes kann ich im Moment noch keine Aussagen machen, da Wochenende ist Wink Auf dem Macbook läuft er auch gut.

Schönen Abend euch.

Gruß
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

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
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

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.