std::threads in richtiger Reihenfolge?
-
Hallo,
angenommen ich habe mehrere threads die etwas erledigen, mich interessiert aber immer nur das Ergebnis des zuletzt gestarteten (also des "aktuellsten") threads.
Also wie im unterem Beispiel-Code: Es werden 10 threads der Reihe nach gestartet. Dabei gibt der Parameter i der thread-Funktion die "Aktualität" des threads an: Je höher i, desto "neuer".
Ist ein thread fertig, soll er sein Ergebnis ausgeben, aber nur wenn ihm nicht ein aktuellerer thread zuvorgekommen ist.
Ist die hier verwendete Methode gut/dafür geeignet?
Ein potenzielles Problem was ich sehe ist das i bzw. highest_i irgendwann überlaufen kann wenn man jetzt keine feste Anzahl an threads erzeugt, sondern über einen längeren Zeitraum hinweg. Das kann man zwar durch Verwendung von long long anstatt int hinauszögern, aber wirklich sauber ist das ja nicht, oder?
#include <iostream> #include <thread> #include <string> #include <mutex> std::mutex m; int highest_i = -1; void output_something(int i) { std::lock_guard<std::mutex> lock(m); if (i > highest_i) // Output only if thread was "newer" { highest_i = i; std::cout << i << '\n'; } } void foo(int i) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Do some work output_something(i); } int main() { for (int i = 0; i < 10; ++i) { std::thread t(foo, i); t.detach(); } std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Ensure all threads are finished (Hack for this example) }
-
happystudent schrieb:
Ist die hier verwendete Methode gut/dafür geeignet?
Nein, besser wäre es, einfach 9 auszugehen.
Das Programm ist völlig sinnlos, aber die geteilten Daten werden korrekt mit einem Mutex geschützt.Du scheinst etwas ganz tolles vorzuhaben, verrätst aber nicht, was. Daher mein allgemeiner Rat: schau dir TBB an, das kann es wahrscheinlich besser als du.
-
manni66 schrieb:
Nein, besser wäre es, einfach 9 auszugehen.

Das wäre dann vom Verhalten aber nicht äquivalent. Das Program gibt nicht nur 9 aus.manni66 schrieb:
Das Programm ist völlig sinnlos, aber die geteilten Daten werden korrekt mit einem Mutex geschützt.
Du scheinst etwas ganz tolles vorzuhaben, verrätst aber nicht, was. Daher mein allgemeiner Rat: schau dir TBB an, das kann es wahrscheinlich besser als du.
Also ich will keine eigene
parallel_forSchleife oder so implementieren (TBB kenn ich schon)...Ich will folgendes: Der Benutzer soll eine relativ teure Berechnung zu einem beliebigen Zeitpunkt (in einer GUI, aber das sollte nicht relevant sein) starten können. Angenommen der Benutzer startet jetzt eine neue Berechnung bevor die vorherige Berechnung angeschlossen ist und diese neue Berechnung ist schneller fertig als die alte, dann ist das Ergebnis der vorherigen Berechnung nicht mehr interessant, da nicht mehr aktuell. Nur das aktuellste Ergebnis ist von Belangen.
Natürlich könnte ich auch die ältere Berechnung in dem seperaten thread zuerst kontrolliert abbrechen, bevor ich die neue Berechnung starte. Dann hab ich aber das Problem dass der Benutzer das Beenden der Berechnung durch immer neue Eingaben beliebig verzögern kann, was auch nicht sein soll.
-
Merk Dir die ID des zuletzt gestarteten Threads und ignorier die Ergebnisse der anderen.
Das ist aber wirklich nicht ansatzweise schoen, du solltest die alten threads abbrechen oder generell nur einen 'berechnungsthread' haben der dann bei Bedarf 'resetet' wird.
-
Ruvi schrieb:
Merk Dir die ID des zuletzt gestarteten Threads und ignorier die Ergebnisse der anderen.
Ok stimmt, das ist schonmal wesentlich besser als ein Zähler.

Ruvi schrieb:
Das ist aber wirklich nicht ansatzweise schoen, du solltest die alten threads abbrechen oder generell nur einen 'berechnungsthread' haben der dann bei Bedarf 'resetet' wird.
Ja, das Problem mit dem reseten ist halt, dass dann eventuell nie eine Berechnung abgeschlossen wird wenn der Benutzer kontinuierlich neue Anforderungen stellt.
Anfrage 1 <--------------->X Anfrage 2 <---------------------> Anfrage 3 <-----------------> etc.Hier wird nie etwas fertig, da der aktuelle thread immer beim starten einer neuen Anfrage abgebrochen wird. Er sollte aber noch fertig laufen, da die neue Anfrage ja noch nicht fertig ist.
Zum Zeitpunkt x (in der "Grafik" als X markiert) ist die erste Anfrage fertig und deren Ergebnis soll jetzt verwendet werden, da die neue Anfrage zwar schon läuft, aber eben noch nicht fertig ist.
Ich hoffe das ist verständlich so?
-
Ganz ehrlich, das ist ein sehr konstruiertes Problem und da ist der Nutzer dann selber schuld.
Ausserdem hast Du das selbe Problem, mit deinem anderen Loesungsansatz.
Thread1 -----> (Ergebnis wird ignoriert da nicht last thread)
Thread2 -----> (Ergebnis wird ignoriert da nicht last thread
Thread3-/--> (Ergebnis wird ignoriert da nicht last thread)
etc...Du wirst ja irgendeine Art von GUI haben und in diesem GUI musst Du fuer den Nutzer ja irgendeine visuelle "Markierung" haben, dass gerade im Hintergrund etwas arbeitet und das die Aktion die er gerade gestartet hat nicht sofort beantwortet wird.
Der Nutzer will ja irgendein Ergebnis und falls er merkt er hat etwas falsche Eingegeben und will es korrigieren, interessiert Ihn nicht das Ergebnis der Anfrage die er abgebrochen hat.
Es macht also keinen Sinn den anderen Thread weiter arbeiten zu lassen.
-
happystudent schrieb:
manni66 schrieb:
Nein, besser wäre es, einfach 9 auszugehen.

Das wäre dann vom Verhalten aber nicht äquivalent. Das Program gibt nicht nur 9 aus.Es liefert das von dir gewünschte Ergebnis schneller und mit gerigerem Resourcenverbrauch.
-
happystudent schrieb:
Anfrage 1 <--------------->X Anfrage 2 <---------------------> Anfrage 3 <-----------------> etc.Hier wird nie etwas fertig, da der aktuelle thread immer beim starten einer neuen Anfrage abgebrochen wird. Er sollte aber noch fertig laufen, da die neue Anfrage ja noch nicht fertig ist.
Welchen Sinn hat das veraltete Ergebnis dann?
Wenn du keinen Thread abbrichst, kann der Benutzer hunderte starten (vielleicht weil er glaubt, dass nichts passiert). Dann wird er erst recht kein Ergebnis erhalten.
-
Hm, hab das alles noch mal durchgedacht und ihr habt wohl recht... macht insgesamt nicht so viel Sinn was ich da vorhatte

Aber trotzdem Danke für die Diskussion
