Seite 1 von 1

Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Sonntag 4. Juli 2021, 16:16
von CSchilling
Grüßt euch,

mich treibt erneut eine Frage um, auf die ich nicht so recht eine Antwort finde. :ugeek:
Ich habe mir die letzten Tage einige Postings durchgelesen und auf YT verschiedene Videos zum Thema Multiprocessing und Threading angesehen.

Für mich kam dabei heraus, dass mein Script ehr CPU basiert arbeitet und nicht auf I/O Opperationen zurückgreift. Lediglich das einlesen der Daten im ersten Schritt, anschließend werden nurnoch Berechnungen durchgeführt.

Es geht mir darum, dass ich den unterhalb beschriebenen Prozess deutlich beschleunigen möchte, sofern das möglich ist.

Es geht darum, dass ich ein Script habe welches in einem ersten Schritt, Daten per csv-modul von meinem PC einließt, diese Daten in einem Dictionary "speichert" und diese dann im folgenden verwendet, Berechnungen, Vergleiche anstellt und dann wieder in einem Dict. "speichert" und von dort aus per csv-modul wieder in eine Datei schreibt. Der Ganze Prozess dauert aktuell ca. 90 Minuten.
Das Dictionary enthält 19 Key:Value Paare. Der dem Key zuegordnete Value ist jeweils eine Liste mit jeweils 650.000 Einträgen.

Im Folgenden rufe ich eine Funktion auf, welche eine Liste Zeile für Zeile von Index 0 an durchläuft und dabei auf Kriterien in der gleichen Zeile untersucht.
Wenn ein Kriterium zutrifft (ganz vereinfacht gesagt, aber Sinngemäß entsprechend: Wert in Liste1 an Stelle 10 > Wert in Liste2 an Stelle 10) dann werden weitere Funtkionen aufgerufen in denen die Werte aus der zutreffenden Zeile verrechnet und in einem anderen Dictionary "gespeichert" werden.

Hierbei ist wichtig zu wissen, dass die einzeln aufgerufenen Funktionen auf die Werte ("gespeichert" im Dictionary) der zuvor aufgerufenen Funktion zurückgreifen. Somit ist die folgende Funktion immer erst aufrufbar, wenn die vorherige Funktion ihre Berechnung abgeschlossen hat.

Kurzes Beispiel:
Wenn nun ein Kriterium erfüllt ist, dann rufe ich die Funktion calc_profit(last_price) auf. Diese Funktion berechnet nun den erziehlten Profit aus dem letzten Preis, schreibt die berechnete Größe in ein Dictionary. Im Anschluss wird dann eine weitere Funktion calc_new_balance()aufgerufen welche aus dem Dictionary den zuvor berechneten Profit abruft und den neuen Kontostand berechnet.

Nachdem nun für das Kriterium alle Funktionen aufgerufen wurden und alle Werte berechnet sind, wird zur ursprünglichen Funktion zurückgekehrt, in der die Liste weiter, Zeile für Zeile durchlaufen wird.

Es gibt noch zahlreiche weitere Funktionen, welche aber alle auf dem selben Schema wie oben beschrieben agieren. Es wird alles über das "speichern" und "lesen" in den Dictionarys und Listen erledigt.

Keine der Funktionen returned einen Wert.

Ich würde euch gerne Beispielcode hier reinstellen, nur fällt es mir schwer den passenden Part aus den 500 Zeilen Code hier reinzustellen.

Mir wäre geholfen, wenn ihr mir sagen könntet ob ich zur Beschleunigung nun auf einen Prozessbasierten Ansatz (Multiprocessing) oder auf einen Threadbasierten Ansatz (Concurrent-Futures, Threading) setzen sollte.


Vielen lieben Dank für eure erneute Hilfe.
Viele Grüße

Christian

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Sonntag 4. Juli 2021, 16:53
von Sirius3
Bevor man mit Parallelisierung anfängt, sollte man die Datenverarbeitung so effizient schreiben, wie möglich. Ohne Deinen Code zu kennen, kann man natürlich nichts definitives sagen, aber ich würde als erstes sagen, dass man statt Wörterbücher und Listen Pandas mit Dataframes nutzen könnte.

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Sonntag 4. Juli 2021, 17:52
von narpfel
Wenn numpy oder pandas keine Option ist, solltest du dir PyPy angucken, das ist viel™ schneller als das normale CPython. Vielleicht reicht das ja schon und du kannst dir einen Haufen Arbeit sparen?

Und da du ja nicht IO-bound bist, sollte dir deine Recherche ja sehr schnell verraten haben, ob du Mutiprocessing oder Threading brauchst.

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Sonntag 4. Juli 2021, 18:37
von kbr
Deiner Beschreibung nach setzen einige Berechnungen die Ergebnisse vorhergehender Berechnungen voraus. In dem Fall scheidet Parallelisierung voraussichtlich aus (oder Du kannst Chargen von key-value pairs unabhängig voneinander behandeln - dann könnte es doch gehen. Aber wenn, dann als Multiprocessing, nicht Multithreading). Insofern ist es sinnvoll, zunächst den einen Prozeß zu beschleunigen. Z.b. wie von narpfel vorgeschlagen per PyPy oder - nach einem Profiler-Run - selektiv mittels Cython oder numba. Bei geeignete Anwendungsfällen kann letzteres ausgesprochen effizient sein.

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Sonntag 4. Juli 2021, 20:11
von CSchilling
Sirius3 hat geschrieben: Sonntag 4. Juli 2021, 16:53 Bevor man mit Parallelisierung anfängt, sollte man die Datenverarbeitung so effizient schreiben, wie möglich. Ohne Deinen Code zu kennen, kann man natürlich nichts definitives sagen, aber ich würde als erstes sagen, dass man statt Wörterbücher und Listen Pandas mit Dataframes nutzen könnte.
Ich würde den Code gerne hier zur Verfügung stellen. Jedoch weiß ich nicht ob das in einem Forum etwas über zu viel verlangt ist, als Hilfe. Das Script hat mit ausführlichen Docstrings und Kommentaren 418 Zeilen. Falls interesse besteht, ich wär über konsturktive Kritik immer sehr dankbar.

Ich werde erstmal den pypy interpreter versuchen und schauen was das an Zeitverbesserung mit sich bringt. Pandas muss ich mich erst einmal einarbeiten wie ich das in dem Code einsetzen kann. :ugeek:


Vielen Dank für die bisherigen Ratschläge!
Schönen Sonntag Abend noch

Grüße, Chris

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Sonntag 4. Juli 2021, 22:17
von Sirius3
418 Zeilen sind jetzt nicht so viel und es hilft mehr, als lange Erklärungen.

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Montag 5. Juli 2021, 11:04
von einfachTobi
Ich wette ein Bier darauf, dass Numpy/Pandas die Berechnungen erheblich beschleunigen können und Parallelisierung nicht erforderlich ist. Der Code würde mich auch interessieren.

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Montag 5. Juli 2021, 13:14
von CSchilling
einfachTobi hat geschrieben: Montag 5. Juli 2021, 11:04 Ich wette ein Bier darauf, dass Numpy/Pandas die Berechnungen erheblich beschleunigen können und Parallelisierung nicht erforderlich ist. Der Code würde mich auch interessieren.
Hehe :D... die Wette wirst du auf alle Fälle gewinnen!! Wäre für mich auch lieber, denn mir kommt das ganze Thema Parallelisierung vor, wie Rakentenwissenschaft :?
Sirius3 hat geschrieben: Sonntag 4. Juli 2021, 22:17 418 Zeilen sind jetzt nicht so viel und es hilft mehr, als lange Erklärungen.
@Sirius3 @einfachTobi der WeTransfer-Link enthält die 216MB große .txt-Datei in der die Basis-Daten als csv gespeichert sind. Ebenfalls findet ihr dort den python3 Code.

https://we.tl/t-Da9X5dnK2F

Als Kriterien für den im Code durchzuführenden Backtest, habe ich aktuell nur zwei(von fünf) Kriterien eingebaut. Die weiteren Kriterien wollte ich noch überarbeiten, diese verändern den Code wie ich ihn im Link oben zur Verfügung gestellt habe, nicht. Es sind lediglich weitere Kriterien auf den
selben Grundlagen wie Long/Buy-Order3 und Short/Buy-Order2.

Über hilfreiche Anregungen aller Art wäre ich sehr Dankbar.

Grüße, Chris

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Montag 5. Juli 2021, 13:31
von sparrow
Und man muss sich mehr als 200 MB herunterladen, um 400 Zeilen Code zu sehen, weil...?

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Montag 5. Juli 2021, 13:53
von CSchilling
sparrow hat geschrieben: Montag 5. Juli 2021, 13:31 Und man muss sich mehr als 200 MB herunterladen, um 400 Zeilen Code zu sehen, weil...?
musst du nicht?!
Du kannst auch nur den Code runterladen, welcher wenige KB groß ist. Sind zwei unabhängige Dateien in dem Link.

Ich wollte nun nicht den Post hier mit 400 Zeilen Code vollstopfen.

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Montag 5. Juli 2021, 13:56
von __blackjack__
Ein ganzer Haufen "Funktionen" die auf einer Menge globaler Wörterbücher operiert. Also die schlechteste Ausgangsposition irgendwas parallelisieren zu wollen. Das würde ich als erstes mal angehen da richtige Funktionen daraus zu machen mit Argumenten und Rückgabewerten und ohne globale Variablen.

Beziehungsweise der allererste, einfache Schritt wäre bei mir die `update_information_variable()`-Funktion zu entfernen. Die macht was triviales, und das aber unnötig kompliziert. Warum wurde da nicht einfach die `update()`-Methode verwendet? Und die Funktion wird auch noch überall so umständlich aufgerufen das erst ein literales Wörterbuch erstellt wird, das mit ``**`` beim Aufruf auf Schlüsselwortargumente verteilt wird, die dann aber wieder mit ``**`` in der Funktionssignatur in einem Wörterbuch gesammelt werden‽

Re: Multiprocessing oder Threading (Concurrent-Futures)?

Verfasst: Montag 5. Juli 2021, 15:40
von CSchilling
__blackjack__ hat geschrieben: Montag 5. Juli 2021, 13:56 Beziehungsweise der allererste, einfache Schritt wäre bei mir die `update_information_variable()`-Funktion zu entfernen. Die macht was triviales, und das aber unnötig kompliziert. Warum wurde da nicht einfach die `update()`-Methode verwendet? Und die Funktion wird auch noch überall so umständlich aufgerufen das erst ein literales Wörterbuch erstellt wird, das mit ``**`` beim Aufruf auf Schlüsselwortargumente verteilt wird, die dann aber wieder mit ``**`` in der Funktionssignatur in einem Wörterbuch gesammelt werden‽
Das hab ich erledigt.
__blackjack__ hat geschrieben: Montag 5. Juli 2021, 13:56 Ein ganzer Haufen "Funktionen" die auf einer Menge globaler Wörterbücher operiert. Also die schlechteste Ausgangsposition irgendwas parallelisieren zu wollen. Das würde ich als erstes mal angehen da richtige Funktionen daraus zu machen mit Argumenten und Rückgabewerten und ohne globale Variablen.
Hmm mir fällt es als Beginner schwer, eine Vorstellung zu bekommen, wie ich die Abfrage der einzelnen Daten ohne die Wörterbücher bzw. globale Variablen bewerkstelligen soll. Der Aufbau einer richtigen Funktion mit Argumenten und Rückgabewerten habe ich verstanden. Nur muss ich die Rückgabewerte ja auch zwischenspeichern, sodass ich diese am Ende als csv ausgeben lassen kann.

Für mich war bisher der Ausgang der selben, ob ich nun eine Funktion einen Wert in einer Liste/Wörterbuch/Variable speicher, oder den Wert als Rückgabewert ausgibt und dann an eine andere Funktion übergibt oder zwischenspeichert.