Seite 1 von 2

threading ?

Verfasst: Samstag 9. Oktober 2010, 13:21
von Xynon1
Hi,

Ich bräuchte mal wieder Hilfe,
ich habe ein Funktion die sieben mal parallel ausgeführt werden müsste aber unterschiedlich schnell endet,
also am Ende müsste ich auf alle sieben warten
Es handelt sich hierbei um recht kurze Zeitspannen.

Die Funktionen müssen Gleichzeitig ausgeführt werden, da diese der Visualisierung dienen und ich alle gleichzeitig ändern möchte.

Wie ist das am besten zu realisieren ?

Danke schon mal wieder im vorraus.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 14:42
von BlackJack
@Xynon1: Du könntest versuchen Threads zu verwenden, aber bei Visualisierung stellt sich die Frage wie diese passiert. GUI-Toolkits mögen es im Normalfall zum Beispiel nicht, wenn von Anderen als dem Hauptthread auf die GUI zugegriffen wird. Wie man dass dann zusammen bringt, hängt vom GUI-Toolkit ab.

Ansonsten kannst Du auch noch versuchen ohne Threads auszukommen, wenn sich die Funktionen so gestalten lassen, dass sie "schrittweise" arbeiten. Zum Beispiel Generatorfunktionen welche die zu visualisierenden Daten generieren. Da kann man dann alle sieben der Reihe nach abfragen und jeweils ihren nächsten Datenpunkt darstellen.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 15:05
von Xynon1
der generator ist scheint mir eine gute idee.
Sollte bei den geringen Zeitfenstern eigentlich keine Probleme geben.

Generatoren

Verfasst: Samstag 9. Oktober 2010, 15:34
von Xynon1
Stellt sich mir nur die frage wie kann ich 7 (eventuell auch weniger oder mehr) gleichzitig laufen lassen?

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 15:50
von DasIch
Die Frage die du dir stellen musst ist nicht wie du sie gleichzeitig zum laufen bekommst, sondern wie du sie so laufen lässt dass es erscheint sie laufen gleichzeitig ab. Du kannst die Realität ohnehin nicht abbilden, der Trick ist soviel davon abzubilden dass du damit davon kommst.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 15:58
von Darii
Xynon1 hat geschrieben:ich habe ein Funktion die sieben mal parallel ausgeführt werden müsste aber unterschiedlich schnell endet,
also am Ende müsste ich auf alle sieben warten
Richtig, eine andere Wahl hast du nicht, denn
Die Funktionen müssen Gleichzeitig ausgeführt werden, da diese der Visualisierung dienen und ich alle gleichzeitig ändern möchte.
„gleichzeitig“ und „unterschiedlich schnell“ schließen sich nunmal aus.

Also, Berechnungen wie auch immer anstellen und danach in einem einzigen Thread die Visualisierung realisieren. Wie BlackJack schon schrieb sind GUI-Toolkits normalerweise nicht threadsicher.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 16:02
von Xynon1
@DasIch ja, ist mir klar

trotzdem müssen alle sieben Generatoren zeitnahe initialisiert werden (zeitgleich laufen).
Und dann abwechselt mir die Daten geben.

Aber wie rufe ich die Generatoren auf, so das ich immer in der reihenfolge g1, g2, ..., g7, g1, g2, ...
die Daten bekomme ?

@Darii

Es handelt sich um Tkinter

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 16:11
von Darii
Xynon1 hat geschrieben:trotzdem müssen alle sieben Generatoren zeitnahe initialisiert werden (zeitgleich laufen).
Und dann abwechselt mir die Daten geben.
Warum müssen sie das? Lohnen sich threads bei dir überhaupt? Python hat den GIL, deswegen laufen Threads prinzipiell sowieso nicht gleichzeitig und extra Prozesse sind teurer als Threads und da deine Funktionen ja schnell sind ist die Frage ob sich das dann immer noch lohnt.
Aber wie rufe ich die Generatoren auf, so das ich immer in der reihenfolge g1, g2, ..., g7, g1, g2, ...
die Daten bekomme ?
Die Frage wurde schon beantwortet. Entweder indem du sie nacheinander aufrufst oder indem du die Threads startest und danach auf alle Threads wartest (mit Thread.join).

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 16:16
von DasIch
Xynon1 hat geschrieben:Aber wie rufe ich die Generatoren auf, so das ich immer in der reihenfolge g1, g2, ..., g7, g1, g2, ...
die Daten bekomme ?
Sowas in dieser Richtung(ungestestet):

Code: Alles auswählen

from itertools import cycle
def foo():
    yield 1
    yield 2
    yield 3

generators = [foo() for _ in xrange(7)]
exhausted = 0
for generator in cycle(generators):
    try:
        print generator.next()
    except StopIteration:
        exhausted += 1
        if len(generators) == exhausted:
            break

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 16:29
von Xynon1
@Darii
Wenn ich die Treads nutze bräuchte ich ja die generatoren nicht, aber BlackJack schrieb:
BlackJack hat geschrieben:Ansonsten kannst Du auch noch versuchen ohne Threads auszukommen, wenn sich die Funktionen so gestalten lassen, dass sie "schrittweise" arbeiten. Zum Beispiel Generatorfunktionen welche die zu visualisierenden Daten generieren. Da kann man dann alle sieben der Reihe nach abfragen und jeweils ihren nächsten Datenpunkt darstellen.
@DasIch
Danke in itertools hatte ich schon gesucht, aber über cycle bin ich leider nicht sofort gestolpert, werde das gleich mal testen aber das sieht schon mal gut aus

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 17:04
von BlackJack
Die Lösung von DasIch dürfte so nicht allgemein funktionieren, weil ein Iterator der "am Ende" ist, *jedesmal* die Ausnahme auslöst, und nicht jeder nur einmal. Wenn "unterschiedlich lang laufen" auch meint, dass die eine unterschiedliche Anzahl von Datenpunkten liefern, dann geht das so nicht. Wenn sie alle gleich viele Datenpunkte liefern, dann kann man sich auf der anderen Seite das Zählen sparen und gleich bei der ersten Ausnahme die Schleife verlassen.

Ich würde da eine Schleife schreiben und jedesmal eine neue Liste aufbauen mit den Generatoren die noch nicht am Ende sind. Wenn die dann leer ist, weiss man das alles fertig ist.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 17:13
von Xynon1
weiß ich - baue ich auch gerade daran - aber mir hat ja vorher jeglicher ansatz gefehlt

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 17:20
von Xynon1
So siehts jetzt aus:

Code: Alles auswählen

while len(gens) > 0:
    for index, gen in enumerate(gens):
        if not gen.next():
            del gens[index]
Hinweis: Meine generatoren geben als letztes false zurück nach dem sie die Schleife verlassen haben

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 18:02
von BlackJack
@Xynon1: Warum geben die `False` zurück? Das ist nicht die vorgesehene API.

Aus Listen zu löschen, über die man gerade iteriert, funktioniert nicht wie man das möchte, weil der Iterator nichts davon mitgekommt, dass alle folgenden Elemente um eine Position verrutscht sind. Darum habe ich ja auch geschrieben dass ich in der Schleife jeweils eine neue Liste erstellen würde mit den Iteratoren die noch nicht am Ende sind.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 18:08
von Xynon1
ist also Zufall das das jetzt gut ein paar dutzend mal ohne Fehler und zu meiner vollsten Zufriedenheit ging ? :shock:

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 18:17
von Xynon1
Ich iteriere ja eigentlich nur mit .next(), und da dies nicht aufgerufen wird, sollte es da nicht egal sein ?

also mein Generator sieht zusammen gefasst so aus:

Code: Alles auswählen

def generator():
    breakpoint = False
    while not breakpoint:
        if ... == ...:
            breakpoint = True
        yield True
    yield False
und das die diese Werte zurück geben ist reiner missbrauch, denn eigentlich brauche ich den generator ja nur um abwechselnt die Funktionen aufzurufen.

Für mich ist das einfach nur das Signal generator läuft noch oder ist zuende.
Ich weiß nicht gerade schick aber bisher ging es ohne Probleme.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 18:56
von BlackJack
@Xynon1: Ja das ist Zufall dass das zu Deiner vollsten Zufriedenheit läuft. Jedesmal wenn Du mit ``del gens[index]`` einen Iterator entfernst wird der Folgende in der Liste beim nächsten Schleifendurchlauf übersprungen. Es geht nicht um das `next()` was Du da aufrufst, sondern dass welches implizit in der ``for``-Schleife steckt.

Wenn gar keine Werte generiert werden, dann würde ich dafür auch keine Generatorfunktion verwenden. Das ist IMHO ähnlicher Missbrauch wie List Comprehensions nur wegen der Seiteneffekte zu verwenden und nicht weil man eine Liste aufbauen möchte.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 19:11
von Xynon1
Tja aber was dann wenn nicht generatoren, und ja es gibt werte aber die werden direkt an die GUI gegeben. War schließlich auch deine idee xD, gut du wusstest nicht das ich diese keine Werte liefern würden.

Ich bin für jeden Vorschlag offen.

Ach und das mit dem überspringen - gibt es eine Möglichkeit den iterator wieder auf start zu setzen, offensichlich nicht, oder ?
Bzw was passiert wenn der der Generator immer neu zugewiesen wird, wird dann die referenz auf den alten gesetzt und würde dort weiter interieren wo der alte aufgehört ha, eigentlich unlogisch da eine neue instanz gebildet werden sollte ? - Ich habe hier wohl eindeutig klärungs bedarf.

Re: threading ?

Verfasst: Samstag 9. Oktober 2010, 20:03
von BlackJack
@Xynon1: Ich glaube Du hast das Problem nicht verstanden. Wenn Du eine Liste mit sagen wir mal drei Elementen hast, und darüber iterierst und im ersten Schleifendurchgang das erste Element aus der Liste entfernst, dann rücken die anderen beiden Elemente eine Position nach vorne. Und im zweiten Schleifendurchgang bekommst Du dann nicht das zweite, sondern das dritte Element -- denn das ist ja jetzt dort wo das zweite vorher war. Effektiv wird also das zweite Element in der Schleife nicht berücksichtigt.

Meine Idee war, dass die Generatorfunktionen die Werte generieren, die dann in der GUI dargestellt werden. In dem Fall gäbe es ja richtige Werte. Und Logik und GUI wären an der Stelle auch sauber voneinander getrennt.

Wenn man nichts generiert, kann man ja Klassen schreiben bei denen eine Methode immer den nächsten Schritt ausführt und darstellt.

Was meinst Du mit Generator immer wieder neu zuweisen und neuen Instanzen erstellen? Ich meinte sowas hier (ungetestet):

Code: Alles auswählen

    while generators:
        new_generators = list()
        for generator in generators:
            try:
                data = generator.next()
            except StopIteration:
                pass    # Intentionally ignored.
            else:
                new_generators.append(generator)
                # TODO Do something with data.
        generators = new_generators

Re: threading ?

Verfasst: Sonntag 10. Oktober 2010, 00:07
von Darii
Xynon1 hat geschrieben:@Darii
Wenn ich die Treads nutze bräuchte ich ja die generatoren nicht, aber BlackJack schrieb:
Das eine hat mit dem anderen nichts zu tun, du kannst auch mit Threads Generatoren verwenden. Irgendwie verstehe ich nicht, was dein Problem ist.