Hi,
ich habe folgendes Problem:
Ich habe einen Gruppe Threads A1-An und eine zweite Gruppe von Thread B1-Bm.
Diese beiden Gruppen formen nun eine Art Ring, dass heißt die Summe der Ausgaben der A Threads ist die Eingabe für die B Threads.
Die Ausgabe von denen ist wiederum die Eingabe für die A Threads.
Was ich nun haben möchte ist folgendes:
Es laufen erst alle A Threads, sobald alle A Threads fertig sind gehen sie ins wait und die B Thread starten.
Bs gehen ins wait, wenn alle im wait sind gehen die As wieder los. Rince and Repeat.
Ich brauche also irgendeine Form der Synchronisation zwischen den Threads. Die Frage ist nun welchen? (Bin halt kein Experte fürs Threading und bevor ich jetzt wilde Konstrukte anfange wollte ich erst eure Meinung einholen).
Ich würde mir also entweder einen Dual Semaphore oder eine Dualbarriere schreiben.
Bei beiden ist die Idee das die As das release für die Bs geben und die Bs das release für die As.
Die Frage ist nun:
Ist das eine gute Idee oder ist das total durchgeknallt?
Liebe Grüße,
p90
Zwei Gruppen von Threads abwechselnd laufen lassen?
@p90: Muss man das unbedingt mit Threads (direkt) lösen? Ich würde immer erst einmal schauen ob es nicht mit ”higher level”-APIs wie `concurrent.futures` lösbar ist.
Alternativvorschlag:
Durch die Queues ist sichergestellt dass entweder A oder B aktiv ist, ganz ohne seperate Synchronisationskonstrukte. Diese musst du auch nicht selbst erstellen, was selbst ein Experte mit hoher Wahrscheinlichkeit falsch machen würde.
Sollten A und B keine State haben, verwende concurrent.futures wie von BlackJack vorgeschlagen.
- Zwei weitere Threads CA und CB, die A bzw. B koordinieren.
- 2 Queues CA->CB und CB->CA mit einer maximalen Größe von jeweils 1
Durch die Queues ist sichergestellt dass entweder A oder B aktiv ist, ganz ohne seperate Synchronisationskonstrukte. Diese musst du auch nicht selbst erstellen, was selbst ein Experte mit hoher Wahrscheinlichkeit falsch machen würde.
Sollten A und B keine State haben, verwende concurrent.futures wie von BlackJack vorgeschlagen.
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Falls es concurrent.Futures nicht sein soll - obwohl das besser wäre -, dann geht auch sowas hier, Python >=3.2 vorausgesetzt:Ist ungetestet und dient nur zur Illustration. Immerhin spart man sich so ca. die Hälfte der Threads.
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
from queue import Queue
from threading import Barrier, Thread
def foo(queue):
queue.put(...)
def bar(queue):
some_value = queue.get()
def main():
number_of_threads = 123
foo_barrier = Barrier(number_of_threads)
bar_barrier = Barrier(number_of_threads)
queue = Queue()
def driver():
while True:
foo(queue)
foo_barrier.wait()
bar(queue)
bar_barrier.wait()
for _ in range(number_of_threads):
Thread(target=driver).start()
if __name__ == '__main__':
main()
In specifications, Murphy's Law supersedes Ohm's.
Hallo,
erst mal Herzlichen Dank für die Tipps, future.concurrents kannte ich z.B. noch gar nicht.
Lese jetzt erstmal genau nach wie ich mit denen mein Problem umsetze und melde mich dann nochmal!
Vlt. noch ein Wenig Kontext um was es genau geht.
Und zwar möchte ich einen Sudoku Erzeuger/Löser schreiben. Dabei will ich das Sudoku aber auf Zellen und Gruppen abbilden um z.B. Samurai Sudoku
oder andere Formen auch direkt zu erschlagen. Die Idee ist dabei, dass ich erst die benötigten Zellen definiere, die dann in alle Gruppen packe zu der sie gehören und dann bi jeder Zelle sehe, welchen wert sie noch annehmen kann und sobald ich ihr einen Wert zuweise wird das durch alle Gruppen und Zellen propagiert.
Die Idee ist nun, die Zellen sind die A Threads, die Gruppen die B Threads. Wenn eine Zelle merkt, dass sie neue Informationen hat markiert sie isch als Tainted, hat diese Information alle B Threads erreicht laufen die los um zu sehen, ob sich aus dieser Information nun neue Information für andere Zellen bildet.
erst mal Herzlichen Dank für die Tipps, future.concurrents kannte ich z.B. noch gar nicht.
Lese jetzt erstmal genau nach wie ich mit denen mein Problem umsetze und melde mich dann nochmal!
Vlt. noch ein Wenig Kontext um was es genau geht.
Und zwar möchte ich einen Sudoku Erzeuger/Löser schreiben. Dabei will ich das Sudoku aber auf Zellen und Gruppen abbilden um z.B. Samurai Sudoku
oder andere Formen auch direkt zu erschlagen. Die Idee ist dabei, dass ich erst die benötigten Zellen definiere, die dann in alle Gruppen packe zu der sie gehören und dann bi jeder Zelle sehe, welchen wert sie noch annehmen kann und sobald ich ihr einen Wert zuweise wird das durch alle Gruppen und Zellen propagiert.
Die Idee ist nun, die Zellen sind die A Threads, die Gruppen die B Threads. Wenn eine Zelle merkt, dass sie neue Informationen hat markiert sie isch als Tainted, hat diese Information alle B Threads erreicht laufen die los um zu sehen, ob sich aus dieser Information nun neue Information für andere Zellen bildet.
@p90: Und das kann man nicht ohne Threads lösen die das alles komplexer machen, aber auf CPython ziemlich sicher kein Stück schneller?