np.power
è una universal function (ufunc). Queste funzioni possono essere utilizzate su scalari e array che hanno una varietà di tipi di dati diversi, ma devono prima verificare il tipo di valori di input in modo che possano determinare quale loop interno utilizzare per generare valori di output adatti.
Se i tipi di input non si associano a nessuno dei loop predefiniti di ufunc, l'ufunc proverà a cast the input values to suitable types (a meno che non venga indicato diversamente). Questo controllo e conversione dei valori di input ha un costo di prestazione ad esso associato, che spiega i tempi osservati nella domanda.
L'attributo types
di un ufunc mostra come i tipi di dati di input verranno mappati su un tipo di dati di uscita. Di seguito è riportato l'elenco delle mappature per 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']
numeri a virgola mobile appartengono al codice di carattere 'g'
, interi Python appartengono 'l'
. Un elenco completo di questi codici carattere può essere trovato here.
Si noti che per questo ufunc, i tipi di dati dei due valori di input devono essere uguali. Ad esempio, non esiste alcuna mappatura per un mix di tipi di dati di input float
e int
input.
Ma possiamo ancora dare np.power
tipi di dati diversi e lasciarli trasmettere i valori ai tipi di dati appropriati. Per un float
ed un int
, un numero float64
viene restituito:
>>> np.power(3.71242, 7).dtype
dtype('float64')
sopra si può vedere che l'unico input che associa al codice float64
carattere g
è di due altri g
valori: 'gg->g'
.
Così, dietro le quinte, ha preso un np.power(3.71242, 7)
Python float
e Python int
e ha dovuto decidere quale potrebbe tranquillamente rifusione e di quale tipo. Il valore int
è stato promosso in modo sicuro a un tipo float g
. L'ufunc allora sapeva quale ciclo eseguire e restituiva un altro valore g
.
Per questo motivo, il mancato mix dei tipi di dati di input offre prestazioni migliori per np.power
.
Se dovessi azzardare un'ipotesi, numpy si aspetta un float ma ha ricevuto un int e aveva bisogno di convertire. –
@JeffMercado idea interessante --- ma non sembra proprio sommare: "% timeit -n 100000 -r 10 if (type (2) == int): float (2)" ==> "100000 loop, best of 10: 571 ns per loop " – DilithiumMatrix
Sospetto che un esponente int sia causa di una moltiplicazione effettiva mentre un esponente float causa l'uso dei log. –