2014-11-06 7 views
7

Ich habe diese Zahlen zufällig gewählt, aber diese Ergebnisse scheinen konsistent zu sein - ein Float-Exponent ist 25% -50% schneller als eine ganze Zahl. Wie werden diese unterschiedlich gehandhabt?Warum ist numpy.power für ganzzahlige Exponenten langsamer?

In [209]: %timeit -n 100000 -r 100 np.power(3.71242, 7) 
100000 loops, best of 100: 3.45 µs per loop 

In [210]: %timeit -n 100000 -r 100 np.power(3.71242, 7.0) 
100000 loops, best of 100: 1.98 µs per loop 
+0

Wenn ich eine Vermutung wagen musste, erwartet numpy einen Float, erhielt aber einen int und musste konvertieren. –

+0

@JeffMercado interessante Idee --- aber es scheint nicht ganz zu addieren: "% Zeit Zeit -n 100000 -r 10 if (type (2) == int): float (2)" ==> "100000 loops, best of 10: 571 ns pro Schleife " – DilithiumMatrix

+0

Ich vermute, dass ein int-Exponent eine tatsächliche Multiplikation verursacht, während ein float-Exponent die Verwendung von Protokollen verursacht. –

Antwort

13

np.power ist ein universal function (ufunc). Diese Funktionen können für Skalare und Arrays mit verschiedenen Datentypen verwendet werden, müssen jedoch zuerst den Typ der Eingabewerte überprüfen, damit sie bestimmen können, welche interne Schleife zum Generieren geeigneter Ausgabewerte verwendet werden soll.

Wenn die Eingabetypen keiner der vordefinierten Schleifen von ufunc zugeordnet sind, versucht ufunc cast the input values to suitable types (sofern nicht anders angegeben). Diese Überprüfung und Umwandlung von Eingabewerten hat einen damit verbundenen Leistungsaufwand, der die in der Frage beobachteten Zeitpunkte erklärt.

Das Attribut types eines ufunc zeigt, wie Eingabedatentypen einem Ausgabedatentyp zugeordnet werden. Unten ist die Liste der Zuordnungen für np.power:

>>> np.power.types # 'input input -> output' 
['bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', 'll->l', 'LL->L', 'qq->q', 
'QQ->Q', 'ee->e', 'ff->f', 'dd->d', 'gg->g', 'FF->F', 'DD->D', 'GG->G', 'OO->O'] 

Gleitkommazahlen in Zeichencode gehören 'g', gehören Python ganzen Zahlen 'l'. Eine vollständige Liste dieser Zeichencodes finden Sie unter here.

Beachten Sie, dass für diese ufunc die Datentypen der beiden Eingabewerte identisch sein müssen. Es gibt beispielsweise keine Zuordnung für eine Mischung aus float und int Eingabedatentypen.

Aber wir können immer verschiedene Datentypen geben und lassen Sie die Werte auf entsprechende Datentypen. Für ein float und ein int, eine float64 Zahl zurückgegeben:

>>> np.power(3.71242, 7).dtype 
dtype('float64') 

Above Sie, dass der einzige Eingang g Karten zum float64 Zeichencode zu sehen, die g Werte zwei andere ist: 'gg->g'.

Also, hinter den Kulissen, nahm np.power(3.71242, 7) eine Python float und eine Python int und zu entscheiden hatte, auf die sie sicher und welche Art neu zu fassen könnte. Der int Wert wurde sicher zu einem Float-Typ g heraufgestuft. Der ufunc wusste dann, welche Schleife ausgeführt werden sollte, und gab einen weiteren g-Wert zurück.

Aus diesem Grund führt das Nicht-Mischen von Eingabe-Datentypen zu einer besseren Leistung für np.power.