Anfängerfrage - Zeitproblem

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
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

Hallo zusammen,
ich habe ein Berechnungs-Programm geschrieben, daß ziemlich lange läuft,
so 1 bis 3 Tage bis es fertig ist. Prinzipiell läuft alles es in einer while Schleife
bis das Ergebnis gefunden wird. (was aber jetzt keine Rolle spielt)
Nun will ich, ohne das Hauptprogramm in der Schleife zu beeinflussen, jede
bestimmte Zeiteinheit, z.B. jede Stunde, eine Anzeige über den Fortschritt,
also z.B. eine einfache Anzeige einer Variable des Programms erhalten.

Wie kann man dieses Problem lösen.
Bin dankbar für jeden Vorschlag.

Gruß
Digitalhans
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Quellcode wäre gut.
Ansonsten gibt es die Module time oder datetime. Damit kannst du die Systemzeit abfragen und dir was daraus basteln.
Wie ermittelst du in deinem Programm Fortschritt?
Vielleicht kannst du diesen einfach immer wieder in eine Datei schreiben?
Wenn aber eine einzelne Berechnung wirklich 24h - 72h brauch, kann man natürlich nichts wegschreiben.
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

Danke für die schnelle Antwort.
Sourcecode ist nur eine einfache while-schleife und darin einige Berechnungen und random Generierungen
mit if Abfragen, mehr nicht. Mein Problem ist, ich will die Zeitfunktionen nicht in der whileschleife, die
milliardenfach läuf und da das Programm ja sowieso schon so lange braucht und jeder zusätzliche Code darin
das Ganze noch weiter verlängert. Es müsste also so etwas geben wie einen timer setzen und dieser soll
dann unabhängig von der Schleife nach x Sekunden einen Variablenwert ausgeben.
Ist so etwas möglich?

Gruß
Digitalhans
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja, aber nicht so, wie von dir gewuenscht. Man kann zwar Threads fuer so etwas nehmen, aber da Python's GIL eh erzwingt, dass diese sich serialisieren wirst du trotzdem deinen Wunsch nach ungestoerter Weiterverarbeitung fahren lassen muessen.

Und da Threads auch obendrein ein komplexes und fehlertraechiges Thema sind, wuerde ich das nicht machen.

Der Ansatz in deiner while-Schleife periodisch zu pruefen ist schon der richtige. Ich wuerde dir empfehlen statt einfach anzunehmen, dass das die Gesamtrechenzeit ungebuehrlich verlaengert, das wirklich auszuprobieren. Entweder machst du den check wirklich effektiv, oder du refaktorierst zB nach diesem Muster:

Code: Alles auswählen

while True: # "alte" schleife
   if should_log():
      log()
   for _ in range(1000000):
       work() # ungestoert fuer lange zeit, der range-iterator und das for sind ziemlich billig
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

OK Danke sehr,
dann werde ich mich um eine Lösung innerhalb der Schleife bemühen.
Welche möglichst einfache und wenig rechenintensive Timerfunktion wäre denn zu empfehlen?
Mir fehlt leider mangels Wissen und Erfahrung leider :oops: noch der Überblick was am Besten dafür wäre.
Danke jetzt schon für die super Hilfe bisher :-)

Gruß
Digitalhans
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@digitalhans: bei mehreren Tagen Rechenzeit kann es sich auch lohnen, zu schauen, wo wieviel Rechenzeit verbraucht wird und eventuell hier zu fragen, ob es nicht schneller geht.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein simples "time.monotonic()" reicht, dazu ein Vergleich mit einem Zeitstempel in der Zukunft:

Code: Alles auswählen

next_logtime = time.monotonic() + LOGPERIOD
while True:
    if time.monotonic() > next_logtime:
           ...
           next_logtime = time.monotonic() + LOGPERIOD
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

Super Danke :-)
werde ich nachher gleich versuchen

Gruß
Digitalhans
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@digitalhans: bei drei Tagen Rechenzeit würde ich auch erst einmal schauen, wo diese hauptsächlich verbraten wird. Lassen sich die Berechnungen womöglich parallelisieren und/oder nach C auslagern, etc. ?
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

Bei der Rechenzeit denke ich wird man nicht so viel rausholen können,
aber wie erwähnt bin ich ja noch Anfänger in Python.
Ich simuliere quasi einen Affen der auf eine Tastatur tippt und lasse den
solange tippen bis er ein bestimmtes Wort getippt hat. Das ist alles. Dabei
zähle ich die Versuche und die Zeit. Dabei untersuche ich z.B. die Unterschiede
zwischen z.B. "Johann" und "johann" und wie die "Arbeitszeit" des Affen mit der
Länge des Wortes steigt.
Zur Rechenzeit: Aktuell braucht mein Affe 1,193 e-06 Anschlägen pro Sekunde,
macht also also knapp 1 Mio Anschläge/Sek., recht flott denke ich. (inklusive der Abfragen des Wortes )

Zurück zu meiner Anfrage. Ich möchte jetzt, dass ich jede Stunde einen
Zwischenstand sehe, um auch zu wissen dass noch alles läuft, aber generell
ist dies genau so notwendig wie das gesamte Programm selbst :D

Bitte auch keine Fragen warum ich dies mache ;-)

Gruß
Digitalhans
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@digitalhans: auch wenn sich das Problem einfach anhört, kann man es doch auf verschiedene Art und Weise lösen, meine primitive Pythonlösung findet "johan" z.B nach 15127861 Zeichen und 9.3s macht 1.6Mio Zeichen pro Sekunde. Meine zweite Lösungsidee hat dann zufällig 14548546 Zeichen gebraucht bei 5.7s macht 2.5Mio Zeichen pro Sekunde, also deutlich schneller. Schreibt ich das ganze mit numpy, sind es z.B. 15178129 Zeichen nach 0.253s was 60Mio Zeichen pro Sekunde sind.

Du siehst also, je nach Implementierung sind es mal 3 Tage mal 2 Stunden für die selbe Rechnung.
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

hmhmh, bei mir braucht es schon sehr viel mehr Versuche bis "johan" getippt wird.
Meistens ca. 120 Millionen Mal.
Meine "Grundgesamtheit" entnehme ich aus random.choice(string.ascii_letters).
Das mit numpy hört sich ja gewaltig an. Da werde ich aber noch viel Lernen müssen denke ich.
Werde mich schon mal reinlesen/üben.

Danke für diese hilfreiche Information.

Grüße
Digitalhans
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

So könnte das mit numpy aussehen:

Code: Alles auswählen

def count_characters(wort):
    zeichen = numpy.array(string.ascii_lowercase, dtype='c')
    start = 0
    old = numpy.random.choice(zeichen, len(wort))
    while True:
        buchstaben = numpy.random.choice(zeichen, 99999)
        buchstaben[:len(wort)] = old
        idx = buchstaben.tobytes().find(wort)
        if idx >= 0:
            return start + idx + len(wort)
        start += len(buchstaben) - len(wort)
        old = buchstaben[-len(wort):]
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Also zum Passwortknacken via Bruteforce würde ich ja eher etwas fertiges nehmen...
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

@Sirius3
Vielen Dank für Dein Beispiel.
Ich werde alles durcharbeiten bis ich alles verstanden habe.

@snafu
Man darf von sich nicht immer auf andere schließen ;-)
Meine Intensionen Python zu lernen und speziell dieses
Programm sind andere, wie auch schon beschrieben.

Grüße
Digitalhans
digitalhans
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2017, 09:06

@Sirius3
Habe Deinen Code in meinen eingebaut und nach dem ich mein Problem mit dem Fehler
"a-bytes-like-object-is-required-not-str" gefunden hatte ist das Ergebnis echt der Hammer.
Das Programm rechnet nun ca. 100 !!! Mal schneller als mein altes.
Ich habe schon gesehen, Python gefällt mir immer mehr und mehr :-)

Danke nochmal für die Hilfe und beste Grüße
Digitalhans
Benutzeravatar
miracle173
User
Beiträge: 127
Registriert: Samstag 6. Februar 2016, 00:28

@digitalhans Wenn du glaubst das das ein Aufruf einer Zeitfunktion zu lange dauert, dann zähle einfach die Schleifenaufrufe mit, das kostet fast nichts. Und bei jedem 1000-sten Schleifenaufrufe misst du die Zeit. Damit reduzierst du die Anzahl der Aufrufe einer Zeitfunktion auf ein Promille.

Oder, nachdem dein Programm etwa 1e6 Schleifendurchläufe pro Sekunde macht, gib einfach nach allen 3.6e9 Schleifendurchläufen den Status aus.
Antworten