Topic: [risolto]Numpy più lento della nativa random?  (Letto 149 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline tommyb1992

  • python neanderthalensis
  • ****
  • Post: 289
  • Punti reputazione: 0
    • Mostra profilo
[risolto]Numpy più lento della nativa random?
« il: Settembre 17, 2018, 14:54 »
Come è possibile?

>>> cProfile.run('for _ in range(1000000): numpy.random.randint(1,3)')
         1000003 function calls in 2.935 seconds

>>> cProfile.run('for _ in range(1000000): numpy.random.choice([1,2])')
         1000003 function calls in 6.875 seconds

>>> cProfile.run('for _ in range(1000000): random.choice([1,2])')
         3000003 function calls in 1.470 seconds

>>> cProfile.run('for _ in range(1000000): random.randint(1, 2)')
         3000003 function calls in 2.171 seconds


E poi come è possibile che randint sia più veloce di choice nella libreria std?

Grazie
« Ultima modifica: Settembre 18, 2018, 10:42 da tommyb1992 »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.821
  • Punti reputazione: 9
    • Mostra profilo
Re:Numpy più lento della nativa random?
« Risposta #1 il: Settembre 17, 2018, 17:50 »
Mah, a parte che non è proprio cProfile lo strumento che userei per questo... comunque, non è il caso d'uso di Numpy.
Prova a confrontare numpy.random.randint(1, 3, size=50) con qualunque equivalente che riesci a fare in Python, e poi mi saprai dire chi va più veloce...

> E poi come è possibile che randint sia più veloce di choice nella libreria std?

Beh, anche a guardare il tuo esempio, è al contrario. Choice è più veloce di randint. Perché ti aspettavi diverso?
Comunque basta leggere il sorgente per capire perché. Entrambe le funzioni sono implementate in termini di randrange, solo che choice fa una cosa semplice, mentre randint deve usare randrange in modo più elaborato.
Del resto guarda, tutte queste funzioni pescano un numero casuale a scelta tra 5 (dalla più veloce alla più lenta):


>>> import timeit
>>> timeit.timeit('random.choice([1, 2, 3, 4, 5])', 'import random')
2.170174988454164
>>> timeit.timeit('random.randrange(5)', 'import random')
2.39225124441964
>>> timeit.timeit('random.randrange(0, 5)', 'import random')
2.8907907835991864
>>> timeit.timeit('random.randint(1, 5)', 'import random')
3.4234043208298317
>>> timeit.timeit('random.randrange(1, 10, 2)', 'import random')
3.7748769264981092

Come vedi, choice e randrange (usato nel modo più semplice) si equivalgono quasi. Se inizi a usare randrange in modo via via più complicato (tra cui randint), i tempi si allungano.

Offline tommyb1992

  • python neanderthalensis
  • ****
  • Post: 289
  • Punti reputazione: 0
    • Mostra profilo
Re:Numpy più lento della nativa random?
« Risposta #2 il: Settembre 17, 2018, 18:39 »
Citazione
Mah, a parte che non è proprio cProfile lo strumento che userei per questo... comunque, non è il caso d'uso di Numpy.
Perchè ho molto codice che sfrutta tecnologie euristiche che utilizzano massivamente le funzioni random e volevo sapere, dato il profilg, se conveniva sostituire le funzioni base con numpy.

Citazione
Beh, anche a guardare il tuo esempio, è al contrario. Choice è più veloce di randint. Perché ti aspettavi diverso?


A dir la verità volevo scrivere esattamente il contrario, pensavo che randint > choice, immaginavo che facesse un passaggio in più (salvare l'array) e quindi ci mettesse di più, ma poco male.

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.821
  • Punti reputazione: 9
    • Mostra profilo
Re:Numpy più lento della nativa random?
« Risposta #3 il: Settembre 18, 2018, 09:32 »
> sfrutta tecnologie euristiche
?

> volevo sapere, dato il profilg
eh ma ti sarai accorto, suppongo, che non ha molto senso usare cProfile per questo.

>  immaginavo che facesse un passaggio in più (salvare l'array)
e che "array" vuoi che "salvi"? Davvero, leggi il codice sorgente, è più semplice di quello che credi. E del resto, se ti stai buttando in questo genere di ottimizzazioni, leggere il sorgente è una cosa che forse vuoi fare comunque.


Comunque, Numpy non è pensato per tirar fuori numeri casuali uno a uno. La forza di Numpy tipicamente è nei suoi array, quando devi maneggiare "in blocco" un grande numero di dati. Ora, se il tuo problema prevede tra l'altro una "massiva" produzione di numeri casuali, allora così a spanne scommetto che troverai un algoritmo del genere MOLTO lento:

for _ in range(10000):
    n = random.randint(1, 5)
    do_something_with(n)

un algoritmo del genere ANCORA PIU' lento, come già ti sei accorto:

for _ in range(10000):
    n = numpy.random.randint(1, 5)
    do_something_with(n)

ma un algoritmo così, molto più veloce:

numbers = numpy.random.randint(1, 5, size=10000)
for n in numbers:
    do_something_with(n)

Offline tommyb1992

  • python neanderthalensis
  • ****
  • Post: 289
  • Punti reputazione: 0
    • Mostra profilo
Re:Numpy più lento della nativa random?
« Risposta #4 il: Settembre 18, 2018, 10:42 »
Citazione
> sfrutta tecnologie euristiche
?

Algoritmi euristici, ora spero sia più chiaro :)

Citazione
Comunque, Numpy non è pensato per tirar fuori numeri casuali uno a uno. La forza di Numpy tipicamente è nei suoi array, quando devi maneggiare "in blocco" un grande numero di dati. Ora, se il tuo problema prevede tra l'altro una "massiva" produzione di numeri casuali, allora così a spanne scommetto che troverai un algoritmo del genere MOLTO lento:
...

Si infatti valuterò in base alle casistiche, grazie

Offline riko

  • python deus
  • *
  • moderatore
  • Post: 7.447
  • Punti reputazione: 12
    • Mostra profilo
    • RiK0 Tech Temple
Re:Numpy più lento della nativa random?
« Risposta #5 il: Settembre 20, 2018, 12:05 »
La gente che fa sta roba tipicamente usa massicciamente numpy.
Come ti hanno fatto notare, devi progettare il codice sulla computazione matriciale, perche' e' molto piu' veloce (non solo i numeri random).

Se non sai/vuoi/puoi farlo, probabilmente numpy non e' per te.

Detto fra noi... quando mi parli di "computazione" e "python" nella stessa frase e non vuoi usare uno dei pochi strumenti che hai per non andare piano, mi verrebbe da dirti di cambiare linguaggio.