Execution speed auf verschiedenen Rechnern

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
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Hallo an alle,

Ich habe kürzlich eine für mich recht überraschende Beobachtung gemacht. Ich habe ein script um md5 hashes zu erstellen (siehe unten angehängt) und habe mit dem timeit Modul das mal Probe laufen lassen (ca. 400 Dateien; prinzipiell alle vergleichbarer typ; audiodateien; ca. 1,4 GB)
Bei meinem alten laptop (1.73 GHz Single core, 2 GB RAM, Ubuntu Lucid) dauerte der Durchlauf im Schnitt 50 Sek. und zu meiner Überraschung bei meinem PC (2.1 GHz Dual Core, 4 GB RAM, Win XP) im Schnitt ca. 0.46 Sek (?!?). Es war mir klar, dass mein PC schneller sein wird, aber "so viel" schneller.

Gibt es da noch andere Faktoren, außer Prozessor Geschwindigkeit und RAM? Lade ich mein RAM voll und die Festplatte muss dann mithelfen? Meines Erachtens, wenn nicht weiter angegeben, benutzt ein Python Skript auch nur einen Prozessor, oder? Wenn mir das einer erklären könnte wäre das nett.

Es geht mir nicht, um das Optimieren des Skripts (zu Verbesserungsvorschlägen sage ich aber wie immer nicht nein), sondern wirklich nur darum zu verstehen, warum da so ein Riesengeschwindigkeitsunterschied ist.

-------------------------------

Hier das Skript:

Code: Alles auswählen

import hashlib
import os
import timeit

def create_md5():

    li = []

    for root, dirs, files in os.walk(os.getcwd()):
        
        for f in files:
        
            m = hashlib.md5()

            with open(os.path.join(root, f), "r") as g:
                while True:
                    data = g.read(128)
                    if not data:
                        break
                    m.update(data)

                d = (f, m.hexdigest())
                li.append(d)

    with open("hash.txt", "w") as g:
        for i in li:
			g.write(i[1])
			g.write("\t")
			g.write(i[0])
			g.write("\n")

if __name__ == "__main__":
    t = timeit.Timer("create_md5()", "from __main__ import create_md5")
    print t.timeit(1)
lunar

@Nebelhom: Dein Skript misst nicht nur die Berechnung der MD5-Hashes selbst, sondern insbesondere auch die Festplattenzugriffe zum Lesen der Daten. Die alte Festplatte Deines Notebooks ist mit Sicherheit wesentlich langsamer als die moderne Deines PC-Systems. Auch sind Notebook-Festplatten generell meist langsamer als Desktop-Festplatten, da sie langsamer drehen und weniger Cache haben.

Restrukturiere Dein Skript mal so, dass Du die Dateien vorweg einliest, und miss dann nur die Berechnung der Hashes. Allerdings besser nur mit der Hälfte der Dateien, und auf dem alten Notebook auch ohne gestartete Desktop-Umgebung auf der Textkonsole, um zu vermeiden, dass das System ob der Datenmenge auslagern muss. Der Unterschied wird dann wahrscheinlich wesentlich geringer ausfallen.
BlackJack

@Nebelhom: Ich weiss Dir ging es nicht um das Optimieren des Programms, aber die Anzahl der gelesenen Bytes pro `read()` ist sehr klein — kleiner als die Puffer, die Betriebssysteme üblicherweise verwenden. Du machst da also deutlich mehr Aufrufe als nötig wären.

Ausserdem würde ich mal prüfen ob da die gleichen Werte heraus kommen — denn unter Windows musst Du die Dateien im Binärmodus öffnen, wenn garantiert der *gesamte* Inhalt der Datei geprüft werden soll, so wie er auf der Platte steht. Nur wenn das Skript auch tatsächlich das gleiche macht, kann man die Zeiten sinnvoll vergleichen.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Noch ein kleiner Tipp.

Statt:

Code: Alles auswählen

for i in li:
    g.write(i[1])
    g.write(i[0])
Besser:

Code: Alles auswählen

for name, digest in li:
    g.write(digest)
    g.write(name)
Stefan
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Hi,

sorry für die relativ späte Antwort. Es ist schon erstaunlich. Habe jetzt mal das XP meines Laptops (Dual boot) angestrengt und das Skript darauf laufen lassen. In XP braucht das Skript für dieselbe Datenmenge tatsächlich nur 0.50 Sek. und ist somit also nur marginal langsamer als der PC. Da hatte BlackJack wohl (mal wieder) Recht ;). Wieder was gelernt. Danke euch allen für die Einblicke.

@BlackJack: Die sache mit den 128 bytes habe ich aus diesem Stack Overflow Eintrag - beliebteste Antwort. Nur so als Erklärung wie ich auf die 128 gekommen bin.

@sma: thanks ;)
BlackJack

@Nebelhom: Heisst das Du hast einfach nur auf XP gewechselt oder hast Du auch *den Fehler* im Programm beseitigt und die Dateien im Binärmodus geöffnet?

Zu den 128 Bytes stehen in den Antworten auf die am höchsten bewertete Antwort noch Anmerkungen, die einen von 128 eigentlich wieder abbringen sollten.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

@BlackJack: Ich hatte gestern Abend nicht viel Zeit, weshalb ich das Skript so gelassen habe, wie es ist, und es nur auf XP mit derselben Datenmenge habe laufen lassen. Die Annahme war, wenn das Skript gleich ist und das Betriebssystem gleich ist (XP), ist deine angesprochene, mögliche Diskrepanz nicht mehr da, weil das Betriebssystem es ja auf allen Rechnern genauso machen "sollte"... oder habe ich da wieder etwas nicht verstanden? Wie gesagt, gestern abend war leider nicht viel Zeit. Mal sehen, ob ich heute noch dazu komme...

Betreff dem StackOverflow Artikel. Da habe ich wohl die letzten 2 Kommentare "überlesen" :oops:

Danke für den Input. Ich finde das hier gerade recht spannend :D
BlackJack

@Nebelhom: Du kannst jetzt zwar die Zahlen vergleichen — sowohl die Hashwerte als auch die Zeiten — aber die Hashwerte sind falsch, beziehungsweise nicht das, was man von so einem Wert erwartet. Der wird normalerweise über die *unveränderten* Bytewerte und über die *ganze* Datei gebildet. *Beides* ist unter Windows *nicht* garantiert wenn man die Datei im Textmodus öffnet. Bei Textdateien werden Bytes/Bytefolgen verändert und es kann sein, dass die Datei nicht komplett verarbeitet wird, sondern ab einem bestimmten Bytewert das Lesen abgebrochen wird.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Ok auf einlesen der Dateien als binaries, bekomme ich am Ende wieder einen vergleichbaren Wert wie in Ubuntu (sprich 50-60 sek.). Ok, das erklärt es. Ich werde das Ganze dann nochmal heute abend an meinem PC machen, aber ich denke der Wert wird dann wohl ähnlich sein.

Noch eine Frage:
Bei Textdateien werden Bytes/Bytefolgen verändert und es kann sein, dass die Datei nicht komplett verarbeitet wird, sondern ab einem bestimmten Bytewert das Lesen abgebrochen wird.
Kennst du den genaueren Grund für das frühzeitige Abbrechen? Steht durch die Veränderung der Bytes/Bytefolgen evtl. mal ein EOF?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Nebelhom hat geschrieben:Steht durch die Veränderung der Bytes/Bytefolgen evtl. mal ein EOF?
Exakt. Und heißt es kthxbai und die restlichen Daten werden völlig ignoriert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Ist das Verändern der Bytes eigentlich eine Windows Eigenart oder eine Python für Windows Eigenart? Weiss das zufällig jemand?
lunar

@Nebelhom: Dieses Verhalten ist in den entsprechenden E/A-Funktionen von Microsofts C-Standardbibliothek MSCRT implementiert, wohl aus historischen Gründen, und betrifft mithin jedes Programm, welches gegen diese Bibliothek gebunden wird, sprich, mit Microsofts C/C++-Compiler übersetzt wurde. Das ist bei den Windows-Binärdateien von CPython der Fall.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

@lunar: Danke für die Erklärung :D
Antworten