Frage

Ich bin eine Anwendung schreiben, die einen mehr Hersteller, einzelnes Consumer-Modell hat (mehr Threads Nachrichten in einen einzigen Datei Writer-Thread senden).

Jeder Hersteller Thread enthält zwei Warteschlangen, eine zu schreiben, in und einen für einen Verbraucher aus zu lesen. Jede Schleife des Verbrauchers Faden, es durch jeden Hersteller iteriert und sperren Mutex ist das Produzent, tauscht die Warteschlangen, entriegelt und schreibt aus der Warteschlange heraus, dass der Hersteller nicht mehr verwendet wird.

Im Consumer-Thread-Schleife, schläft es für eine bestimmte Menge an Zeit, nachdem sie alle Produzenten-Threads verarbeitet. Eine Sache, die ich sofort auffiel, war, dass die durchschnittliche Zeit für einen Hersteller etwas in die Warteschlange zu schreiben und Rück drastisch erhöht (von 5 x), wenn ich von 1 Produzenten Thread zu 2. bewegte Als weitere Themen hinzugefügt werden, diese durchschnittliche Zeit verringert, bis es anstößt out - es gibt keinen großen Unterschied zwischen den mit 10 Produzenten vs 15 Produzenten Zeit genommen. Dies liegt vermutlich daran, mit mehr Herstellern zu verarbeiten, gibt es weniger Konkurrenz für den Mutex Produzenten Thread.

Leider <5 Produzenten haben, ist ein recht häufiges Szenario für die Anwendung, und ich mag die Ruhezeit optimieren, so dass ich eine vernünftige Leistung unabhängig davon, wie viele Hersteller existieren. Ich habe durch die Erhöhung der Schlafzeit bemerkt, dass, ich kann eine bessere Leistung bei niedrigen Erzeugern zählen, aber schlechtere Leistung für große Produzenten zählen bekommen.

Hat jemand anderes diese angetroffen werden, und wenn ja, was war Ihre Lösung? Ich habe versucht, die Ruhezeit mit der Anzahl der Threads Skalierung, aber es scheint ein wenig maschinenspezifische und ziemlich trial-and-error.

War es hilfreich?

Lösung

Sie können die Schlafzeit wählen basierend auf der Anzahl von Herstellern oder auch die Ruhezeit auf einig dyanmic Schema anzupassen machen basiert. Wenn die Verbraucher aufwacht und keine Arbeit haben, die doppelte Schlafzeit, es anders halbieren. Aber beschränken die Ruhezeit bis zu einem gewissen Minimum und Maximum.

Wie auch immer Sie tapezierten über eine grundlegende Frage. Schlafen und Polling ist einfach richtig zu machen und manchmal ist der einzige Ansatz zur Verfügung, aber es hat viele Nachteile und ist nicht die „richtige“ Art und Weise.

Sie können in die richtige Richtung Kopf durch eine Semaphore Zugabe, der erhöht wird, wenn ein Hersteller ein Element in einer Warteschlange hinzufügt und erniedrigt, wenn der Verbraucher ein Element in einer Warteschlange verarbeitet. Der Verbraucher wird nur aufwachen, wenn es Elemente sind so sofort zu verarbeiten und tun.

Polling die Warteschlangen können nach wie vor ein Problem sein, aber. Sie könnten eine neue Warteschlange hinzuzufügen, die auf jede Warteschlange bezieht, die Gegenstände auf sie. Aber es vielmehr stellt sich die Frage, warum Sie nicht eine einzelne Warteschlange, dass der Verbraucher Prozesse eher als eine Warteschlange pro Produzenten. Ceteris paribus, die wie der beste Ansatz klingt.

Andere Tipps

Statt schlafen, würde ich empfehlen, dass Ihre Verbraucher Block auf einem Zustand von den Herstellern signalisiert. Auf einem Posix-kompatiblen System, man könnte es mit pthread_cond arbeiten zu lassen. Erstellen Sie ein Array von pthread_cond_t, eine für jeden Hersteller, dann erstellen Sie ein zusätzliches ein, die zwischen ihnen geteilt wird. Die Produzenten zunächst ihren individuellen Zustand veränderliches Signal, und dann denjenigen geteilt. Die Verbraucher wartet auf den gemeinsam genutzten Zustand und dann iteriert über die Elemente des Arrays, eine pthread_cond_timed_wait() an jedem Element des Arrays Ausführen (Verwendung pthread_get_expiration_np() die absolute Zeit für die „jetzt“ erhalten). Wenn die Wartezeit 0 zurückgibt, dann haben die Erzeugerdaten geschrieben. Der Verbraucher muss die Bedingung Variablen neu initialisiert werden, bevor sie wieder warten.

Durch die Blockade wartet verwenden, müssen Sie die Menge Zeit minimieren die Verbraucher unnötig die Produzenten ist-out zu verriegeln. Sie könnten auch diese Arbeit mit Semaphore machen, wie in einer früheren Antwort angegeben. Semaphore hat Semantik im Vergleich zu Bedingungen vereinfachte, meiner Meinung nach, aber man müßte vorsichtig sein, den gemeinsamen Semaphor für jeden Hersteller einmal zu verringern, die bei jedem Durchlauf durch den Verbraucher Schleife verarbeitet wurde. Bedingungsvariablen hat den Vorteil, dass Sie im Grunde sie wie boolean Semaphore verwenden können, wenn Sie sie neu zu initialisieren, nachdem sie signalisiert werden.

Versuchen Sie eine Implementierung einer Blocking-Warteschlange in der Sprache zu finden, die Sie für die Programmierung verwenden. Nicht mehr als eine Warteschlange für eine beliebige Anzahl von Erzeugern und einem Verbraucher genug sein.

Für mich klingt es wie Sie versehentlich ein gewissen Puffer einführen von dem Verbraucher-Thread woanders beschäftigt sein, die entweder schlafen oder eigentliche Arbeit zu tun. (Die Warteschlange als Puffer wirkt) Vielleicht einige einfache Pufferung auf der Produzentenseite tun wird Ihre Konflikte reduzieren.

Es scheint, dass Ihr System ist sehr empfindlich zu sperren-Streit zwischen dem Erzeuger und Verbraucher, aber ich bin ratlos, warum eine so einfache Swap-Operation genügend CPU-Zeit in Ihrer Lauf Statistiken auftauchen besetzen würde.

Kann zeigen Sie einen Code?

edit: Vielleicht nehmen Sie Ihr Schloss und tauschen Warteschlangen, auch wenn es keine Arbeit zu tun

?
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top