Warum ist der erste Schleifendurchlauf immer rund 2 Sekunden schneller als die Nachfolgenden?

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

Warum ist der erste Schleifendurchlauf immer rund 2 Sekunden schneller als die Nachfolgenden?
Ich setze sogar die zwei Hauptarrays zum Schluß immer auf "None"
Wenn ihr den Code laufen lassen wollt, müßt ihr numpy und primesieve installen und
eine logDatei in dem selben Verzeichniss mit dem Namen "MPMP_19_mit_primesieve.log" mit Inhalt z.B

"[1500000000000, 45624190113149, 1017423309728666061300174678423263757851]

"
erzeugen.
Außerdem bin ich für jede Performanzsteigerung, jeglicher Art, dankbar.
Bin gespannt .... Kalli

Code: Alles auswählen

from sys import stdout
from primesieve.numpy import *
import re
import os, sys
import numpy
import time
import json
import winsound
import linecache

#---------------------------------------------------------------------------

def printundspeichern(p,n,summe,was):
    if was == 'gefunden':
        print("n =",n,"... prime =", p, "... sum of primesquares (accumulated) =", summe, "... so n divides the sum of the Squares:",(summe // n),"times")
        f = open ("MPMP_19_mit_primesieve.log", "a")
        f.write("n = " + str(n) + " ... prime = " + str(p) + " ... sum of primesquares (accumulated) = " + str(summe) + " ... so n divides the sum of the Squares: " + str((summe // n)) + " times" + "\n")
        f.close()
    if was == 'bereich':
        resarray = []
        resarray.append(n)
        resarray.append(p)
        resarray.append(summe)
        f = open ("MPMP_19_mit_primesieve.log", "a")
        f.write(str(resarray)+ "\n")
        f.close()
#---------------------------------------------------------------------------

resarray = []
f = open("MPMP_19_mit_primesieve.log", "r")
linecache.clearcache()
zeile = linecache.getlines("MPMP_19_mit_primesieve.log")[-1]
f.close
neuezeile = ''.join((ch if ch in '0123456789' else ' ') for ch in zeile)
resarray = [int(i) for i in neuezeile.split()]

potenz = 8
ZeitGesamt = 0
n = resarray[0]
letzte = resarray[1]
summe = resarray[2]

ZeitStart = time.time()

for x in range(1,1000000000):
    primesarray  = numpy.array(n_primes(pow(10,potenz), letzte+1), dtype=object) # (Stück, ab Primzahl)   
    gesamtarray  = numpy.cumsum((primesarray * primesarray), dtype=object)

    gesamtarray[-1] += summe
    summe = gesamtarray[-1]        
    n += gesamtarray.size      
    letzte = primesarray[-1]          

    ZeitEnd  = time.time()
    ndigit = int(str(n)[3])
    space = '          '
    print(space[0:ndigit]," Time = %3.3f " % (ZeitEnd - ZeitStart), space[0:(10-ndigit)], "n =", n, "... prime =", letzte, "... sum of primesquares (accumulated) =", summe)
    ZeitStart = ZeitEnd
    if n % (pow(10,potenz + 2)) == 0:
        printundspeichern(primesarray[-1],n,summe,'bereich')
        winsound.Beep(440, 1000)
    primesarray = None
    gesamtarray = None
Sirius3
User
Beiträge: 18219
Registriert: Sonntag 21. Oktober 2012, 17:20

`stdout` wird importiert aber gar nicht benutzt. Das ist auch selten nötig.
*-Importe sind schlecht, weil man nicht nachvollziehen kann, welche Namen importiert werden.
re, os, sys, json werden importiert, aber gar nicht benutzt.
linecache und winsound sind sinnvoll einsetzbar.
Diese komischen Kommentare mit den vielen Minuszeichen sind wenig aussagekräftig, können also weg.
`printundspeichern` sind zwei Funktionen in einer, die durch was unterschieden werden, das sollten eigentlich zwei getrennte Funktionen sein.
Das was in `print` steht ist das selbe, was bei write geschrieben wird, das sollte also nur einmal im Code stehen. Statt Strings mit + zusammenzustückeln benutzt man Stringformatierung.
Dateien öffnet man mit dem with-Statement.
Wenn man eine leere Liste erzeugt, um dann fix mit append etwas hinzufügt, dann kann man gleich die Liste mit Inhalt erzeugen. `resarray` ist auch der falsche Name, weil es eine Liste und kein Array ist. Zudem sollte im Variablennamen keine Abkürzungen vorkommen und keine Datentypen. `result` wäre korrekt.
Die Stringrepräsentation einer Liste ist nicht zum Speichern oder Weiterverarbeiten gedacht. Das ist nur für eine Debugausgabe. Wenn man strukturierte Daten speichern will, benutzt man z.B. json.
Alles ab Zeile 29 sollte auch in einer Funktion stehen, die üblicherweise main genannt wird.
Statt linecache sollte man einfach nur die Datei ganz normal bis zur letzten Zeile lesen.
close sollte man auch aufrufen, aber besser noch with benutzen.
Zum Parsen der letzten Zeile sollte man einen wirklichen Parser benutzen.
Variablennamen schreibt man komplett klein, `ZeitGesamt` wird aber auch gar nicht benutzt.
Die Zeitmessung ist etwas verquer.
Ist es Absicht, dass die Schleife nur 999999999mal durchlaufen wird?
`pow` benutzt man nicht, das ist **.
Es ist nicht sehr effizient immer wieder die selben Primzahlen zu erzeugen.
Warum sind die numpy-Arrays vom Typ object? Da ist es meist besser, eine ganz normale Liste zu benutzen. cumsum wird nicht gebraucht, da Dich eh nur die gesamt-Summe interessiert.
Was Du da mit `ndigit` machst, verstehe ich nicht.
Das was Du da mit space machst, versteh ich daher auch nicht, aber sowas macht man per Formatangaben bei Stringformatierung.
primesarray und gesamtarray auf None zu setzen ist unsinnig, da Du sie ja gleich wieder mit neuen Werten füllst.

Code: Alles auswählen

from primesieve.numpy import n_primes
import time
import json

LOG_FILENAME = "MPMP_19_mit_primesieve.log"

def print_gefunden(p, n, summe):
    text = f"n = {n} ... prime = {p} ... sum of primesquares (accumulated) = {summe} ... so n divides the sum of the Squares: {summe // n} times"
    print(text)
    with open(LOG_FILENAME, "a", encoding="utf8") as output:
        output.write(text + "\n")

def print_bereich(p, n, summe):
    with open(LOG_FILENAME, "a", encoding="utf8") as output:
        json.dump([n, p, summe], output)
        output.write("\n")

def main():
    with open(LOG_FILENAME, "a", encoding="utf8") as lines:
        last_line = list(lines)[-1]
    n, letzte, summe = json.loads(last_line)

    potenz = 8
    anzahl = 10 ** potenz
    for _ in range(999999999):
        start_time = time.monotonic()
        primes = n_primes(anzahl, letzte + 1)
        duration = time.monotonic() - start_time
        summe += sum(p*p for p in primes)
        n += len(primes)
        letzte = primes[-1]
        ndigit = n // 100 & 10
        print(f"{' '*n} Time = {duration:3.3f} {' '*(10-n)} n = {n} ... prime = {letzte} ... sum of primesquares (accumulated) = {summe}")
        if n % (anzahl * 100) == 0:
            print_bereich(letzte, n, summe)

if __name__ == '__main__':
    main()
Karl-Heinz Hofmann
User
Beiträge: 20
Registriert: Dienstag 12. November 2019, 15:34

Vielen lieben Dank für die Mühe. Ich bin überwältigt. Allerdings läuft dein Piece erheblich langsamer. Das liegt wahrscheinlich am Numpy, daß du nicht benutzt hast. Gruß Kalli
Antworten