So schnell wie möglich große tecplot Blockdateien in Python importieren

9

Ich möchte in Python einige ASCII-Dateien importieren (aus tecplot, Software für cfd-Nachbearbeitung). Regeln für diese Dateien sind (zumindest für diejenigen, die ich importieren muss):

  • Die Datei ist in mehrere Abschnitte unterteilt

Jeder Abschnitt hat zwei Zeilen als Header wie:

%Vor%
  • Jeder Abschnitt hat einen Satz von Variablen, der von der ersten Zeile angegeben wird. Wenn ein Abschnitt endet, beginnt ein neuer Abschnitt mit zwei ähnlichen Zeilen.
  • Für jede Variable gibt es I * J * K Werte.
  • Jede Variable ist ein kontinuierlicher Werteblock.
  • Es gibt eine feste Anzahl von Werten pro Zeile (6).
  • Wenn eine Variable endet, beginnt die nächste in einer neuen Zeile.
  • Variablen sind "IJK geordnete Daten" .Der I-Index variiert am schnellsten; der J-Index der nächst schnellste; der K-Index der langsamste. Der I-Index sollte die innere Schleife sein, der K-Index sollte die äußere Schleife sein, und der J-Index die Schleife dazwischen.

Hier ist ein Beispiel für Daten:

%Vor%

Ich bin ziemlich neu in Python und ich habe einen Code geschrieben, um die Daten in ein Wörterbuch zu importieren, indem ich die Variablen als 3D numpy.array schreibe. Diese Dateien könnten sehr groß sein (bis zu Gb). Wie kann ich diesen Code schneller machen? (oder allgemeiner: Wie kann ich solche Dateien so schnell wie möglich importieren)?

%Vor%

Ps. In Python, kein Cython oder andere Sprachen

    
Pierpaolo 06.10.2013, 18:37
quelle

2 Antworten

2

Die Umwandlung einer großen Menge von Strings in Zahlen ist immer ein wenig langsam, aber unter der Annahme, dass die dreifach verschachtelte for-Schleife der Flaschenhals ist, gibt es eine ausreichende Beschleunigung:

%Vor%

Leider habe ich im Moment nur Zugriff auf mein Smartphone (kein PC), also kann ich nicht testen, wie schnell das ist oder ob es überhaupt richtig oder überhaupt funktioniert!

Aktualisieren

Endlich habe ich einige Tests gemacht:

  • Mein Code enthielt einen kleinen Fehler, scheint aber jetzt korrekt zu funktionieren.
  • Der Code mit den vorgeschlagenen Änderungen läuft ungefähr viermal schneller als das Original
  • Ihr Code verbringt die meiste Zeit auf ndarray.itemset und wahrscheinlich auf Overhead- und Float-Konvertierung. Leider zeigt cProfile dies nicht im Detail.
  • Der verbesserte Code verbringt etwa 70% der Zeit in numpy.fromstring , was meines Erachtens darauf hindeutet, dass diese Methode ziemlich schnell ist für das, was Sie mit Python / NumPy erreichen können.

Update 2

Natürlich wäre es noch besser, die Datei zu durchlaufen, anstatt alles auf einmal zu laden. In diesem Fall ist dies etwas schneller (ich habe es ausprobiert) und reduziert die Speicherauslastung erheblich. Sie könnten auch versuchen, mehrere CPU-Kerne zu verwenden, um das Laden und die Konvertierung in Gleitkommazahlen durchzuführen, aber dann wird es schwierig, alle Daten unter einer Variablen zu haben. Abschließend ein Wort der Warnung: Die Methode fromstring , die ich verwendet habe, skaliert ziemlich schlecht mit der Länge der Zeichenfolge. Z.B. ab einer bestimmten Stringlänge wird es effizienter, etwas wie np.fromiter(itertools.imap(float, str_vector.split()), dtype=float) zu verwenden.

    
user2379410 12.01.2014 19:24
quelle
0

Wenn Sie hier reguläre Ausdrücke verwenden, gibt es zwei Dinge, die ich ändern würde:

  • Kompiliere REs, die häufiger verwendet werden (was für alle REs in deinem Beispiel gilt, denke ich). Setzen Sie regex=re.compile("<pattern>") auf ihnen und verwenden Sie das resultierende Objekt mit match=regex.match() , wie in die Python-Dokumentation .

  • Berücksichtigen Sie für die I, J, K REs, zwei REs auf eins zu reduzieren, indem Sie das Gruppierungsmerkmal (oben beschrieben) verwenden, indem Sie nach einem Muster der Form "I = (\ d +)" suchen Ergreifen Sie den Teil, der innerhalb der Klammern mit regex.group(1) übereinstimmt. Wenn Sie dies weiterführen, können Sie eine einzelne Regex definieren, um alle drei Variablen in einem Schritt zu erfassen.

Zumindest zum Starten der Abschnitte scheinen REs etwas übertrieben zu sein: Es gibt keine Variation in der Zeichenfolge, nach der Sie suchen müssen, und string.find() ist in diesem Fall ausreichend und wahrscheinlich schneller.

EDIT: Ich habe gerade gesehen, dass Sie die Gruppierung bereits für die Variablen verwenden ...

    
virtualnobi 10.01.2014 16:08
quelle

Tags und Links