2016-08-05 78 views
6

von der schönen Welt der kommend, ich versuche, dieses Verhalten verstehen:Ist Python intelligent genug, um Funktionsaufrufe mit konstantem Ergebnis zu ersetzen?

In [1]: dataset = sqlContext.read.parquet('indir') 
In [2]: sizes = dataset.mapPartitions(lambda x: [len(list(x))]).collect() 
In [3]: for item in sizes: 
    ...:  if(item == min(sizes)): 
    ...:   count = count + 1 
    ...:   

würde nicht auch nach 20 Minuten beenden, und ich weiß, dass die Liste sizes nicht so groß ist, weniger als 205k Länge. Allerdings ausgeführt diese sofort:

In [8]: min_item = min(sizes) 

In [9]: for item in sizes: 
    if(item == min_item): 
     count = count + 1 
    ...:   

Also, was ist passiert?

Meine Vermutung: konnte nicht verstehen, dass min(sizes) immer konstant sein wird, so dass nach den ersten paar Anrufen mit seiner Rückkehr ersetzen value..since Python das Interpreter verwendet ..


Ref von min() Doesn sage nichts, was mir die Sache erklären würde, aber was ich dachte, ist, dass es vielleicht die Partitionen dafür suchen muss, aber das sollte nicht der Fall sein, da sizes ein list ist , kein RDD!


Edit:

Hier ist die Quelle meiner Verwirrung, ich ein ähnliches Programm in C geschrieben:

for(i = 0; i < SIZE; ++i) 
    if(i == mymin(array, SIZE)) 
     ++count; 

und bekam diese Timings:

C02QT2UBFVH6-lm:~ gsamaras$ gcc -Wall main.c 
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out 
That took 98.679177000 seconds wall clock time. 
C02QT2UBFVH6-lm:~ gsamaras$ gcc -O3 -Wall main.c 
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out 
That took 0.000000000 seconds wall clock time. 

und für Timings habe ich Nomimal Animal Ansatz von meinem Time measurements verwendet.

+1

Der erste Code ist 'O (n * n)', der zweite Code ist 'O (n) '. Wie unterstützt dies die Hypothese? – user2864740

+1

CPython macht nur sehr einfache Optimierungen. Die dynamische Natur der Sprache macht auch viele Optimierungen unmöglich: Stellen Sie sich zum Beispiel vor, wenn ein anderer Code 'min = Lambda x: 1' hätte. –

+3

Es gibt keine nicht-reine Sprache, die ich kenne, die sogar versuchen würde, diese Optimierung zu "verstehen". Um überhaupt gültig zu sein, wäre eine Garantie für deterministisches Verhalten erforderlich. – user2864740

Antwort

5

ich nicht bin, bedeutet ein Experte für das Innenleben des Python, aber aus meinem Verständnis so weit möchten Sie die Geschwindigkeit der

for item in sizes: 
    if(item == min(sizes)): 
     count = count + 1 

und

min_item = min(sizes) 
for item in sizes: 
    if(item == min_item): 
     count = count + 1 

Jetzt vergleichen jemand korrigiert mich, wenn ich etwas davon falsch habe aber,

In Python-Listen sind veränderbar und haben keine feste Länge, und werden als s behandelt uch, während in C ein Array eine feste Größe hat. Von this question:

Python-Listen sind sehr flexibel und vollständig heterogen, beliebige Daten aufnehmen kann, und sie können sehr effizient, in den fortgeführten Anschaffungs konstante Zeit angehängt werden. Wenn Sie Ihr Array zeitsparend und ohne Aufwand verkleinern und vergrößern möchten, sind sie der richtige Weg. Sie benötigen jedoch viel mehr Platz als C-Arrays.

Nun nehmen Sie dieses Beispiel

for item in sizes: 
    if(item == min(sizes)): 
     new_item = item - 1 
     sizes.append(new_item) 

Dann wird der Wert von item == min(sizes) würde bei der nächsten Iteration unterschiedlich sein. Python speichert den resultierenden Wert min(sizes) nicht im Cache, da es das obige Beispiel unterbrechen würde oder eine Logik erfordern würde, um zu überprüfen, ob die Liste geändert wurde. Stattdessen überlässt es dir das. Indem Sie min_item = min(sizes) definieren, speichern Sie das Ergebnis im Wesentlichen selbst.

Jetzt da das Array eine feste Größe in C ist, kann es den minimalen Wert mit weniger Overhead als eine Python-Liste finden, warum ich denke es hat kein Problem in C (sowie C ist eine viel niedrigere Ebene Sprache).

Noch einmal, ich verstehe nicht vollständig den zugrunde liegenden Code und Kompilierung für Python, und ich bin sicher, wenn Sie den Prozess der Schleifen in Python analysiert, würden Sie sehen, Python wiederholt min(sizes) berechnen, was die extreme Menge an Verzögerung. Ich würde gerne mehr über die inneren Abläufe von Python lernen (zum Beispiel, werden irgendwelche Methoden in einer Schleife für Python zwischengespeichert, oder wird alles für jede Iteration neu berechnet?). Wenn jemand mehr Informationen und/oder Korrekturen hat, lass es mich kennt!

+0

Während Sie einen Punkt haben und ich Ihre Antwort akzeptierte, seien Sie gewarnt, dass ich denke, dass es nicht 100% klar ist. Zum Beispiel habe ich dasselbe mit einem 'std :: vector' gemacht und habe 115,9 sec. und 8,4 sec, was trotz der Flexibilität des Vektors eine dramatische Beschleunigung zeigt. Also würde ich sagen, dass es eher ein [tag: python] Ding ist, als eine Frage der Flexibilität der Datenstruktur. – gsamaras