Können Sie in Julia Platz für einen String vorgeben?

8

Die Julia-Dokumentation beschreibt Speicher vorbelegen für Array , um die Leistung zu verbessern, indem die Speicherbereinigung vermieden wird. Ist das möglich mit einem String , das ist schließlich ein Vektor? String Quellcode ist hier .

Mein Anwendungsfall ist, dass ich große Textdumps verarbeite, indem ich readuntil() verwende, um einen Chunk zu erhalten, und dann regex match() oder matchall() oder replace() . Ich habe es bereits in Perl programmiert, möchte aber sehen, ob Julia schneller sein kann. Ich kenne bereits die Länge der längsten Zeichenfolge, die ich verarbeiten muss.

%Vor%

Ich erwarte, dass Festplatten-E / A der größte Engpass sein wird, bin aber daran interessiert, alles zu erfahren, was helfen wird. Ich begrüße alle Vorschläge zu möglichen Methoden, um den Prozess zu beschleunigen.

    
ultradian 19.03.2017, 20:09
quelle

3 Antworten

5

Strings in Julia sind unveränderlich, daher funktioniert das Konzept der Vorbelegung nicht.

%Vor%     
slowbrain 19.03.2017 20:37
quelle
3

Erstens,

  

"Vorzeitige Optimierung ist die Wurzel allen Übels" - Donald Knuth

Nachdem das gesagt wurde, zeigt der replace Code in Base an, dass er den Quellstring liest und Übereinstimmungen findet, die er ersetzen soll, und er schreibt Teile des resultierenden Strings in einen IOBuffer. Nach der Verarbeitung liest es den Output String vom IOBuffer. Im Wesentlichen macht dies zwei Kopien des Quellstrings. Wenn eine maximale Länge des Input-Strings (und damit auch des Outputs) bekannt ist, kann der IOBuffer in replace anstelle von allocated wiederverwendet werden.

Um diese Analyse in Code zu fassen, definieren Sie das folgende replace! (basierend auf replace ):

%Vor%

Und jetzt,

%Vor%

führt einen Austausch durch, ohne den IOBuffer zuzuweisen. Nach dem replace! kann out wiederverwendet werden (es ist wieder leer um takebuf_string in replace! . Benchmarking zeigt, dass dies die Zuteilung um 50% reduziert und auch den Prozess beschleunigt. Wenn viele replace Statements verwendet werden, wie Sie in der Frage vorschlagen, sollte dies eine 30% oder mehr Verbesserung geben.

Wenn Sie das versuchen, wäre es schön, ein echtes Benchmark-Ergebnis zu hören. Vielleicht sollte eine Version von replace! in Base eingefügt werden.

    
Dan Getz 21.03.2017 13:30
quelle
1

In Julia 0.6 ist es einfacher, eine noch optimiertere Version zu versuchen. Insbesondere können ein IOBuffer und ein String den gleichen Speicher teilen. Die Funktion replace schreibt in einen IOBuffer und verarbeitet einen String, so dass wir replace! ohne Zuteilungen ausführen können.

Eine Reihe von replace! -Anweisungen kann zwischen zwei im Voraus zugewiesenen Puffern wechseln und (fast) jegliche Zuweisung vermeiden.

Konkreter:

%Vor%

Und um diese Funktion zu steuern und Puffer vorzubelegen, machen wir:

%Vor%

Die Funktion switcheroo! ersetzt hello durch whats up und wieder zurück. Es ist einfach, den Code so zu ändern, dass er eine Reihe von replace behandelt, wie es die Frage erfordert.

Anmerkungen:

  1. Dies ist enger mit Julia String Interna verbunden und kann daher nicht stabil sein für zukünftige Julia Versionen (aber genauso effiziente Alternativen werden wahrscheinlich bleiben).

  2. Es gibt immer noch zwei (lästige!) Zuordnungen pro replace! für die zwei erstellten SubString-Werte. Diese Zuweisungen sind 64 Bytes und wachsen nicht mit der String-Größe.

Dan Getz 23.03.2017 10:11
quelle