Seite 1 von 1

Random Values mit anschließendem Dictionary, dass n-1 werte aufweist?

Verfasst: Montag 6. Juni 2022, 21:05
von Max22
Hallo

ich habe eine Liste erstellt mit 1000 verschiedenen Werten und auch gemessen wie schnell mein PC benötigt, um diese Liste mit 1000 random Werten zu füllen.

Einmal so:
Das soll angeblich nicht so gut sein die Methode: Kann mir jemand erklären wieso?
import datetime
from datetime import timedelta

def get_time():
return datetime.datetime.now()

timestamp_1 = get_time()

import random
my_randoms = random.sample(range(1,1001),1000)
print(my_randoms)

timestamp_2 = get_time()

passed_time = timedelta.total_seconds(timestamp_2 - timestamp_1)

print("It took", passed_time, " seconds to execute this program")
Dann mit timeit:
Obwohl hier die Liste anscheinend nur im Hintergrund gefüllt wurde. Sie ist nicht im Output zu sehen.
import timeit
import_module = "import random"
testcode = '''
def test():
return random.sample(range(1,1001),1000)
'''
passed_time_2 = timeit.timeit(stmt=testcode, setup=import_module)

print("It took", passed_time_2, " seconds to execute this program")
Wie erstelle ich nun ein Dictionary, dass die Zahlen der gefüllten Liste mit n-1 wiedergibt?

Die Frage lautetet folgendermaßen: "Time in milliseconds how long it takes for a list to be filled
with 1000 random values, then a dictionary to be constructed from the list, with each key being 1 smaller
than its value."

Hab ich es denn überhaupt so richtig verstanden?

Ich sitze heute schon den ganzen Tag daran und versuche irgendwie noch was richtiges im Internet oder in unserem Buch "Automate the boring stuff with python" zu finden. Aber nichts scheint zu klappen. Könnt ihr mir helfen zu verstehen, wie ich die Aufgabe lösen kann?

LG

Re: Random Values mit anschließendem Dictionary, dass n-1 werte aufweist?

Verfasst: Montag 6. Juni 2022, 21:25
von __deets__
Na im ersten Fall misst du ja auch die Ausgabe Zeit mit. Das ist garantiert falsch. datetime ist auch überkandidelt & teuer, time.monotonic würde man eher nehmen. Im zweiten Fall machst du kein print. Dann wird wenig überraschend auch nix ausgegeben.

Und dann zur eigentlichen Aufgabe: du baust ja bisher nur die Liste. Es fehlt aber noch das Bauen des dicts. Zb mit mit einer dict-comprehension. Das muss noch zb in test.

Re: Random Values mit anschließendem Dictionary, dass n-1 werte aufweist?

Verfasst: Montag 6. Juni 2022, 22:08
von __blackjack__
Max22: `timeit` ist hier nicht nur besser sondern `datetime` ist da schlicht ungeeignet für solche Mikrobenchmarks. Rechner machen heute nicht nur eine Sache sondern zig Sachen gleichzeitig, so dass man so kurzen Zeitspannen so viel ”rauschen” mit misst, das man das man den Code sehr oft messen muss und daraus dann einen Mittelwert bilden. Und das in der Regel auch mehrmals. Auf modernen Prozessoren kann dann noch dazu kommen, das der Prozessor je nach angeforderter Rechenleistung vom System runter bzw. höher getatktet wird, und/oder in einen stromsparenden Schlafmodus versetzt wird, wenn nichts los ist. Was dazu führen kann, das die ersten Messungen längere Zeiten messen als spätere wo das System gemerkt hat, das sich was tut und den Prozessor hochtaktet.

`datetime` hat zudem das Problem das die Zeit nicht zwingend immer gleich schnell oder auch vorwärts laufen muss. Schaltsekunden, Zeitkorrekturen via NTP, oder umstellung Winter-/Sommerzeit wären Beispiele. Zudem ist die „wall clock“/Echtzeituhr üblicherweise nicht die Zeitquelle mit der höchten Auflösung die ein Rechner bietet. Das sind meistens Performance-Timer im Prozessor.

Du misst Irrelevantes mit im ersten Ansatz. Der Import vom `random`-Modul und die Ausgabe per `print()` gehören nicht in die Messung. Beides kann die Zeit für die eigentliche Aufgabe locker um mehrere Grössenordnungen übertreffen, weil beim Import vom Hintergrundspeicher geladen und ein Modulinhalt ausgeführt wird, und Ausgaben zwar einfach aussehen, aber ausserhalb verhältnismässig sehr zeitintensive Dinge passieren können, wie Grafikoperationen für die Ausgabe der Daten in einer GUI, die vielleicht von einer Grafikkarte beschleunigt werden, vielleicht aber auch nicht. Da werden Zeiten mitgemessen die schwer vorhersagbar sind und das Ergebnis zur Unbrauchbarkeit verzerren.

Die Aufgabe ist ein bisschen Unterpezifiziert, denn Liste mit 1000 Zufallszahlen sagt weder, dass das ganze Zahlen sein sollen, noch in welchem Wertebereich die sich bewegen sollen, noch das die sich nicht wiederholen dürfen. Entweder steht in der Aufgabe mehr, oder ich hätte Fragen an den Dozenten oder Tutor. Sonst würde ich das schriftlich anmerkerken und einfach `random()` 1000× aufrufen. Die Wahrscheinlichkeit für Doubletten ist bei 1000 Zahlen verschwindend gering und wird durch die Widerholungen die `timeit` macht ausgeglichen.

Re: Random Values mit anschließendem Dictionary, dass n-1 werte aufweist?

Verfasst: Dienstag 7. Juni 2022, 12:45
von Max22
@deets. danke. Stimmt ich Printe nichts.. Aber er misst trotzdem wie lange die Liste gefüllt wird auch wenn nichts im output wiedergegeben wird oder?

@blackjack. danke für die Erklärung von timeit. wenn ich irgendwann mal komplexere Codes schreibe, dann weiß ich wieso ich besser timeit nehme :)

bzgl. der Aufgabe... keine Ahnung. Ich hab bald n treffen mit Kommilitonen, da Besprechen wir es nochmal zusammen

Re: Random Values mit anschließendem Dictionary, dass n-1 werte aufweist?

Verfasst: Dienstag 7. Juni 2022, 13:04
von __blackjack__
@Max22: Nein, nicht bei komplexeren Sachen, gerade bei den total einfachen, kleinen Ausdrücken muss man `timeit` verwenden. Insbesondere hier wo das Ergebnis in Millisekunden schon 0,irgendwas ist, weil man eigentlich Mikrosekunden misst, sollte man nichts selbst gebasteltes verwenden, weil das sehr wahrscheinlich was falsch macht. Besser wäre es noch statt `timeit` das externe `pyperf`-Modul zu verwenden.

Re: Random Values mit anschließendem Dictionary, dass n-1 werte aufweist?

Verfasst: Dienstag 7. Juni 2022, 13:58
von __deets__
Max22 hat geschrieben: Dienstag 7. Juni 2022, 12:45 @deets. danke. Stimmt ich Printe nichts.. Aber er misst trotzdem wie lange die Liste gefüllt wird auch wenn nichts im output wiedergegeben wird oder?
Wenn wir hier in der Philosophie waeren, kann man sich natuerlich die Frage stellen, ob der Baum im Wald ein Geraeusch macht beim umfallen, wenn's keiner hoert. Aber in Python gibt es keine Rueckwirkung von einem irgendwann mal erfolgten print auf vorherigen Code. Was du uebrigens auch einfach haettest selbst testen koennen, du baust ja gerade ein benchmark. Das sollte ja etwas messen abhaengig davon, was du machst. Also eben auch weniger, wenn du *keine* Liste/Dict baust.

Re: Random Values mit anschließendem Dictionary, dass n-1 werte aufweist?

Verfasst: Mittwoch 8. Juni 2022, 11:07
von __blackjack__
Ich habe das mal mit `pyperf` für CPython und PyPy gemacht:

Code: Alles auswählen

$ setup='from random import random'

$ expression='...'  # Hier stand der zu messende Ausdruck.

$ python3.7 -m pyperf timeit --setup "$setup" "$expression"
.....................
Mean +- std dev: 146 us +- 3 us

$ pypy -m pyperf timeit --setup "$setup" "$expression"
........
Mean +- std dev: 122 us +- 2 us
Also 0,146 Millisekunden mit CPython und 0,122 Millisekunden mit PyPy auf einem schon etwas älteren Büro-Desktoprechner.

Edit: Und dann nur mal so zum Spass das importieren und die Ausgabe des Endergebnisses (Wörterbuch) mitgemessen:

Code: Alles auswählen

CPython 3,32 Millisekunden (±0,18)
PyPy    4,33 Millisekunden (±0,16)
Also bei CPython macht das was Du *eigentlich* messen sollst dann nur noch 4,4% an der Gesamtlaufzeit aus und bei PyPy sogar nur 2,8%.