Wiederverwendung thread in der Schleife c++
Brauche ich, um zu parallelisieren, einige Aufgaben, die in einem C++ - Programm und bin völlig neu mit der parallelen Programmierung. Ich habe einige Fortschritte durch internet-Recherchen so weit, aber bin ein wenig stecken jetzt. Ich möchte Wiederverwendung einige threads in einer Schleife, aber offensichtlich nicht wissen, wie zu tun, was ich versuche.
Ich bin mit der Erfassung von Daten aus zwei ADC-Karten auf dem computer (erworben in parallel), dann brauche ich, um einige Operationen durchzuführen, die auf die gesammelten Daten (parallele Verarbeitung), während das sammeln der nächste Stapel von Daten. Hier etwas pseudocode zur Veranschaulichung
//Acquire some data, wait for all the data to be acquired before proceeding
std::thread acq1(AcquireData, boardHandle1, memoryAddress1a);
std::thread acq2(AcquireData, boardHandle2, memoryAddress2a);
acq1.join();
acq2.join();
while(user doesn't interrupt)
{
//Process first batch of data while acquiring new data
std::thread proc1(ProcessData,memoryAddress1a);
std::thread proc2(ProcessData,memoryAddress2a);
acq1(AcquireData, boardHandle1, memoryAddress1b);
acq2(AcquireData, boardHandle2, memoryAddress2b);
acq1.join();
acq2.join();
proc1.join();
proc2.join();
/*Proceed in this manner, alternating which memory address
is written to and being processed until the user interrupts the program.*/
}
Das ist der wichtigste Kern von ihm. Der nächsten Ausführung der Schleife schreiben würde, das "eine" Speicher-Adressen während der Verarbeitung der "b" - Daten und weiterhin abwechseln (ich kann den code dazu, nur nahm es heraus um zu verhindern, unübersichtlich bis das problem).
Trotzdem ist das problem (wie ich bin sicher, manche Leute können das schon sagen) ist, dass die zweite Zeit, die ich versuche zu verwenden acq1 und acq2, der compiler (VS2012) sagt, "IntelliSense: Aufruf an ein Objekt einer Klasse geben, die ohne die entsprechenden operator - () oder das conversion-Funktionen Zeiger auf Funktion vom Typ". Ebenso, wenn ich die std::thread vor acq1 und acq2 wieder, heißt es " Fehler C2374: 'acq1' : Neudefinition; mehrere Initialisierung".
Die Frage ist also, kann ich zuweisen von threads zu einer neuen Aufgabe, wenn Sie abgeschlossen haben Ihre vorherigen Aufgabe? Ich warte schon immer für den vorherigen Einsatz der thread zu Ende bevor Sie es wieder, aber ich weiß nicht, wie die übernahme der thread, und da es in einer Schleife, ich kann nicht machen, einen neuen thread jedes mal (oder wenn ich könnte, scheint verschwenderisch und unnötig, aber ich könnte falsch sein).
Vielen Dank im Voraus
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der einfachste Weg ist die Verwendung einer wartemöglichkeit Warteschlange
std::function
Objekte. Wie diese:while(true)
innerhalb dieser Funktionen zum Lesen und schreiben von Benutzer-stream. Nur die erste Funktion ausgeführt wird, die anderen warten in der Warteschlange! das Konzept der thread-pool mit threads, die Ausführung von Aufgaben, die gleichzeitige durch den Wechsel zwischen Aufgaben.Den
std::thread
Klasse ist so konzipiert, führen genau eine Aufgabe (die, die Sie geben Sie im Konstruktor) und dann ist Ende. Wenn Sie möchten, dass mehr Arbeit zu tun, müssen Sie einen neuen thread. Ab C++11, das ist alles, was wir haben. Thread-pools nicht in die Norm. (Ich bin unsicher, was C++14 ist über Sie zu sagen.)Glücklicherweise können Sie leicht implementieren der erforderlichen Logik selbst. Hier ist das groß angelegte Bild:
Den schwierigsten Teil hier (das ist noch Recht einfach) ist richtig, die Gestaltung der Warteschlange. In der Regel, eine synchronisierte verkettete Liste (aus der STL) für diese. Synchronisiert bedeutet, dass jeder thread, der will manipulieren die Warteschlange muss nur so tun, nachdem es erworben hat, eine
std::mutex
so, um Wettlaufsituationen zu vermeiden. Wenn ein worker-thread findet die Liste leer, es hat zu warten, bis es einige arbeiten wieder. Sie können einestd::condition_variable
für diese. Jedes mal, wenn eine neue Aufgabe eingefügt wird, in der Warteschlange, wird das einlegen thread benachrichtigt ein thread, der wartet auf die condition variable und wird deshalb Blockierung und schließlich starten Sie die Bearbeitung der neuen Aufgabe.Dem zweiten nicht-so-triviale Teil ist, wie signal an die worker-threads, dass es keine Arbeit mehr zu tun. Klar, können Sie einige Globale flag aber wenn ein Arbeiter ist blockiert, wartet an der queue, es wird nicht klar, in absehbarer Zeit. Eine Lösung könnte sein, die
notify_all()
threads und haben Sie überprüfen Sie die Flagge jedes mal, wenn Sie benachrichtigt werden. Eine weitere option ist das einfügen einige deutliche "giftig" Element in die Warteschlange. Wenn ein Arbeiter trifft auf dieses Element, es beendet sich.Repräsentiert eine Warteschlange von Aufgaben ist straight-forward mit Ihren selbst definierten
task
Objekte oder einfach lambdas.Alle der oben genannten sind die C++11-features. Wenn Sie stecken bleiben, die mit einer früheren version haben, brauchen Sie to resort to third-party-Bibliotheken, die multi-threading für Ihre jeweilige Plattform.
Während nichts davon ist Hexenwerk, es ist immer noch leicht zu bekommen, falsch die erste Zeit. Und leider, concurrency-Fehler gehören zu den schwer zu Debuggen. Starten, indem Sie verbringen ein paar Stunden mit dem Lesen der entsprechenden Abschnitte von einem guten Buch oder ein Lernprogramm durcharbeiten können sich schnell auszahlen.
Diese
ist der Aufruf eines Konstruktors. erstellen Sie ein neues Objekt namens acq1
Diese
ist die Anwendung der () - operator auf das vorhandene Objekt aqc1. Wenn es nicht solch ein operator definiert, der für std::thread-der compiler beschwert sich.
Soweit ich weiß, dürfen Sie nicht wiederverwendet std::threads. Erstellen Sie und starten Sie Sie. Gemeinsam mit Ihnen und werfen Sie Weg,
Gut, es hängt davon ab, ob Sie in Erwägung ziehen eine Neuzuweisung oder nicht. Sie können einen thread, aber nicht eine Kopie davon anfertigen.
Folgende code erstellt neue paar threads jeder iteration, und verschieben Sie Sie in Platz des alten threads. Ich denke, das sollte funktionieren, da neue
thread
Objekte werden Provisorien.Was Los ist, das Objekt eigentlich gar nicht zu Ende es ist Leben am Ende der iteration, weil es deklariert ist, in den äußeren Umfang in Bezug auf die Schleife. Aber ein neues Objekt erzeugt wird, jedes mal und
move
stattfindet. Ich sehe nicht, was kann geschont werden (ich vielleicht blöd), damit ich mir vorstellen das es genau das gleiche wie die Deklarationacq
s innerhalb der Schleife und einfach wiederverwenden, das symbol. Alles in allem ... ja, es geht darum, wie Sie zu klassifizieren eine temporäre undmove
.Auch, das ist sicher einen neuen thread startet-each-Schleife (natürlich Ende der vorher zugewiesenen thread), es macht nicht ein thread warten, bis neue Daten und magisch füttern die Verarbeitung von Rohr. Würden Sie benötigen, um zu implementieren, die es anders mögen. E. g: - pool Worker-threads und die Kommunikation über queues.
Referenzen:
operator=
,(en)
.Ich denke, die Fehler, die Sie erhalten, sind selbsterklärend, also werde ich überspringen, Sie zu erklären.
Ich glaube, Sie brauchen eine viel einfachere Antwort für die Ausführung einer Gruppe von threads mehr als einmal, ist dies die beste Lösung:
Sie könnte auch machen Sie Ihren eigenen Thread-Klasse und rufen die Methode ausführen wie: