Multithreading für kleine Aufgaben
Verfasst: 21.03.2013, 16:28
Hallo Leute,
ich verfolge das Forum schon länger, muss nun aber selbst mal meine sorgen los werden :-)
Kurzum: Es geht um einen Iterativen Solver für ein lineares Gleichungssystem mit 1k..2M Unbekannten.
Dabei werden Punktprodule (x dot y), Normen (x dot x), Matrix-Vektormultiplikationen (A*x) und Vektoradditionen (x+c*y) berechnet.
Ein Punktprodukt über sehr große Vektoren geht nur mit hierarchischer Verarbeitung. Also immer nur gruppenweise aufaddieren, dann die Gruppen wieder in Gruppen bis nur noch eine Zahl übrig bleibt.
Ein Lösungsvorgang kann recht lange dauern (10..20min) und dabei rechnet nur eine CPU im ganzen System - das ist sehr schade. Ich würde die Zeit viel lieber halbieren und zwei Threads benutzen, oder sogar mehr, auf Prozessoren mit mehr kernen.
Das Problem ist, dass der algorithmus sehr sequentiell arbeitet. Also berechne ich ein Punktprodukt, wird das auch im nächsten schritt gebraucht. Berechnet ich einen Vektor, wird der auch danach sofort benötigt und hängst selbst vom Schritt vorher ab. bäääh.
Alles was mir übrig bleib ist, die jeweiligen Unteraufgaben in Threads zu unterteilen.
Ich habe versucht das beim Punktprodukt umzusetzen und bin vom ergenis sehr entäuscht. Das Multithreading scheint mehr verwaltungsaufwand zu sein, als die berechnung, sodass ich je mehr Threads ich verwende, umso länger brauche^^ Ich hätte eigentlich lieber das reziproke Verhalten :-D
Zur Zeit gehe ich so vor:
In den Threads:
1) WaitForSingleObject(StartEvent....)
2) Berechnung
3) SetEvent(FertigEvent)
Der Aufrufer macht nur
1) Threaderzeugen
2) Daten aufsetzen
3) SetEvent(StartEvent) für jeden Thread
--- sollte der Thread hier selbst was rechen??
4) WaitForMultipleObjects( bis alle das Threads das FertigEvent gesendet haben)
5) die ergebnisse der einzelnen Threads addieren, fertig.
Ich beobachte nun, dass meine CPU, wenn sie gezwungen ist durchweg sinnlos Punktproduke in Endlosschleife zu berechnen maximal zu ~60% ausgelastet wird.
Die Kommunikation zwischen SetEvent und WaitForSingleObject ist also durchaus mit viel Leerlauf verbunden - die berechnung ist dann schon fast egal. :-(
Richtig krass bemerkbar ist das, wenn der Vektor relativ klein wird.
Die frage ist nun: wie parallelisiert man nun sowas effizient?
Ich selbst habe 6 Kerne / 12 Threads. und keiner bekommt was zu tun :-(
ich verfolge das Forum schon länger, muss nun aber selbst mal meine sorgen los werden :-)
Kurzum: Es geht um einen Iterativen Solver für ein lineares Gleichungssystem mit 1k..2M Unbekannten.
Dabei werden Punktprodule (x dot y), Normen (x dot x), Matrix-Vektormultiplikationen (A*x) und Vektoradditionen (x+c*y) berechnet.
Ein Punktprodukt über sehr große Vektoren geht nur mit hierarchischer Verarbeitung. Also immer nur gruppenweise aufaddieren, dann die Gruppen wieder in Gruppen bis nur noch eine Zahl übrig bleibt.
Ein Lösungsvorgang kann recht lange dauern (10..20min) und dabei rechnet nur eine CPU im ganzen System - das ist sehr schade. Ich würde die Zeit viel lieber halbieren und zwei Threads benutzen, oder sogar mehr, auf Prozessoren mit mehr kernen.
Das Problem ist, dass der algorithmus sehr sequentiell arbeitet. Also berechne ich ein Punktprodukt, wird das auch im nächsten schritt gebraucht. Berechnet ich einen Vektor, wird der auch danach sofort benötigt und hängst selbst vom Schritt vorher ab. bäääh.
Alles was mir übrig bleib ist, die jeweiligen Unteraufgaben in Threads zu unterteilen.
Ich habe versucht das beim Punktprodukt umzusetzen und bin vom ergenis sehr entäuscht. Das Multithreading scheint mehr verwaltungsaufwand zu sein, als die berechnung, sodass ich je mehr Threads ich verwende, umso länger brauche^^ Ich hätte eigentlich lieber das reziproke Verhalten :-D
Zur Zeit gehe ich so vor:
In den Threads:
1) WaitForSingleObject(StartEvent....)
2) Berechnung
3) SetEvent(FertigEvent)
Der Aufrufer macht nur
1) Threaderzeugen
2) Daten aufsetzen
3) SetEvent(StartEvent) für jeden Thread
--- sollte der Thread hier selbst was rechen??
4) WaitForMultipleObjects( bis alle das Threads das FertigEvent gesendet haben)
5) die ergebnisse der einzelnen Threads addieren, fertig.
Ich beobachte nun, dass meine CPU, wenn sie gezwungen ist durchweg sinnlos Punktproduke in Endlosschleife zu berechnen maximal zu ~60% ausgelastet wird.
Die Kommunikation zwischen SetEvent und WaitForSingleObject ist also durchaus mit viel Leerlauf verbunden - die berechnung ist dann schon fast egal. :-(
Richtig krass bemerkbar ist das, wenn der Vektor relativ klein wird.
Die frage ist nun: wie parallelisiert man nun sowas effizient?
Ich selbst habe 6 Kerne / 12 Threads. und keiner bekommt was zu tun :-(