2 konkurierende Funktionen (Threading)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Karl-Heinz Hofmann
User
Beiträge: 20
Registriert: Dienstag 12. November 2019, 15:34

Ich werde mit dem threading nicht schlau. Intensive Recherche im Net brachte auch nichts, dabei sollte das Problem simple zu bewerkstelligen sein.

So zum Thema:
Ich habe zwei Funktionen.

def viaexponent(n):
result = n**5
# hier sollte der Befehl stehen der "viamulti" killt
return result

def viamulti(n):
result = n*n*n*n*n
# hier sollte der Befehl stehen der "viaexponent" killt
return result

Im Hauptprogramm sollen beide simultan gestartet werden und je nachdem welche Funktion zuerst das Ergebnis hat, soll die andere Funktion aktiv stoppen.
Eigentlich ganz simpel. Hab einiges probiert. Und wie sähe der Aufruf im Hauptprogramm aus (mit Parameterübergabe)?
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das geht nicht. Threads kann man nicht killen. Du kannst es mit multiprocessing machen, die kann man abschiessen. Bei derart trivialen Berechnungen wird das aber natuerlich nix, weil die schneller fertig sind, als jedes Kommando zum abbrechen ankommen kann.
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

je nach dem was der Sinn ist, vllt wäre es interessant die Ausführungszeit beider Funktionen zu messen und die dann zu vergleichen?

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Karl-Heinz Hofmann
User
Beiträge: 20
Registriert: Dienstag 12. November 2019, 15:34

Natürlich ist n**5 und n*n*n*n*n nur ein Platzhalter für in meinem Programm weitaus komplexere Funktion. Aus einem Pool von ca. 1000 n- Werte werden die Funktionen beschickt. Bei kleinen
n braucht Funktion A nur 0,5 Sekunden und B 50 Sekunden. Am Schluß, wenn n groß ist, ist es genau umgedreht. Soweit so gut könnte man in der Mitte einen Switchpoint setzen. Aber die Mitte der n Werte
liefert einmal 2 zu 30 Sekunden und der nächste n dann 20 zu 3 Sekunden z.B. Das geht dann für ca. 30 n so hin und her und schlecht vorherzusagen.
Eine Multiprocessing Lösung würde mich brennend interessieren. Bitte
Gruß Kalli
Karl-Heinz Hofmann
User
Beiträge: 20
Registriert: Dienstag 12. November 2019, 15:34

@grubenfox: Auf der Seite war ich schon. Find da aber nix passendes.
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also ich finde da https://docs.python.org/3/library/multi ... .terminate oder auch kill, und das ist angesichts deines Vorhabens sehr passend.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Threads und Multiprocessing arbeiten immer kooperativ. Das heißt, Du mußt in regelmäßigen Abständen abfragen, ob der andere Thread ein threading.Event gesendet hat, dass er fertig ist, und dann kann sich der eigene Thread auch beenden.
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

Mit futures.FIRST_COMPLETED sollte das auch funktionieren..

Code: Alles auswählen

from concurrent import futures

def viaexponent(n):
    result = n**5
    # hier sollte der Befehl stehen der "viamulti" killt
    return result

def viamulti(n):
    result = n*n*n*n*n
    # hier sollte der Befehl stehen der "viaexponent" killt
    return result


if __name__ == '__main__':

    n=10000

    with futures.ProcessPoolExecutor(max_workers=2) as e:
        futs = {e.submit(func, n): func.__name__ for func in [viaexponent,viamulti]}
        res = futures.wait(futs, return_when=futures.FIRST_COMPLETED)

    for func in res.done:
        print(f"{futs[func]}: {func.result()}")
Benutzeravatar
DeaD_EyE
User
Beiträge: 1021
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Threads kann man killen und mache machen sich den Spaß das anderen zu zeigen, damit sie sich selbst ordentlich in den Fuß schießen können.

Wieso soll der Thread gekillt werden? Wieso kann das innerhalb der Funktion nicht durch Logik gelöst werden? Der Thread und/oder Prozess wird beendet, wenn die Funktion verlassen worden ist. Wenn du jetzt für das Problem Multiprocessing nutzt, hast du ein neues Problem: Serialisierung der Daten für den anderen Prozess.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Qubit: Das bricht aber die anderen noch laufenden `Futures` an der Stelle nicht ab. Die werden trotzdem weiter berechnet.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

__blackjack__ hat geschrieben: Mittwoch 28. Februar 2024, 00:35 @Qubit: Das bricht aber die anderen noch laufenden `Futures` an der Stelle nicht ab. Die werden trotzdem weiter berechnet.
Ja, das stimmt wohl.
Da hilft wohl dann nur, die Workerprozesse zu killen, wenn man das Future hat..

Code: Alles auswählen

from concurrent import futures

def viaexponent(n):
    result = n**5
    # hier sollte der Befehl stehen der "viamulti" killt
    return result

def viamulti(n):
    result = n*n*n*n*n
    # hier sollte der Befehl stehen der "viaexponent" killt
    return result


if __name__ == '__main__':

    n=10000
    
    e = futures.ProcessPoolExecutor(max_workers=2)
    futs = {e.submit(func, n): func.__name__ for func in [viaexponent,viamulti]}

    res = futures.wait(futs, return_when=futures.FIRST_COMPLETED)

    for proc in e._processes:
        e._processes[proc].kill()

    e.shutdown()

    for func in res.done:
        print(f"{futs[func]}: {func.result()}")
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Qubit: Das ist nicht wirklich eine Lösung in die Interna von einer fremden Klasse einzugreifen. `_processes` kann existieren, muss es aber nicht. Die Objekte darin können eine `kill()`-Methode haben, müssen sie aber nicht. Wobei `terminate()` auch die freundlichere Wahl an der Stelle wäre.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

__blackjack__ hat geschrieben: Mittwoch 28. Februar 2024, 14:25 Wobei `terminate()` auch die freundlichere Wahl an der Stelle wäre.
Ja, aber wohl mit einer Warnung..
https://docs.python.org/3/library/multi ... .terminate
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und beim kill gilt die gleiche Warnung, der Grund ist ja nun nicht das Signal an den Prozess, sondern der Zustand, der hinterlassen wird.
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Die Warnung steht wahrscheinlich bei `terminate()` weil man da im Gegensatz zum `kill()` noch die Chance hat beim anderen Prozess dieses Problem zu berücksichtigen, und im SIGTERM-Handler die Ressource freizugeben, während man beim `kill()` da ja wirklich nichts mehr machen kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten