duda de optimizacion
Francesc Alted
faltet en pytables.org
Mar Abr 28 12:38:32 CEST 2009
A Tuesday 28 April 2009, Chema Cortes escrigué:
> El día 27 de abril de 2009 3:49, lasizoillo <lasizoillo en gmail.com>
escribió:
> > El segundo es más rápido tambien. Definitivamente x**y parece que
> > mola más.
>
> Son operaciones distintas. math.pow utiliza la librería matemática de
> C, operando con reales en coma flotante; mientras que la segunda
> operación se implementa directamente por el lenguaje. Si la base es
> entera, la segunda operación debería la más eficiente; si son reales,
> en teoría debería ser más eficiente la primera (math.pow), aunque hay
> que precisar más...
>
> Al medir tiempos hay que tener en cuenta la sobrecarga que supone
> pasar los parámetros a la función:
>
>
> def f(n,p): return n**p
>
> timeit 2**100 --> 27.2 ns per loop
> timeit f(2,100) --> 1.92 µs per loop
>
> timeit 2.0**100 --> 27.2 ns per loop
> timeit f(2.0,100) --> 323 ns per loop
>
>
> La sobrecarga del paso de parámetros hace que, paradójicamente, tarde
> más la operación con números enteros (largos) que con reales.
Pues sí que es curioso, yo también lo puedo reproducir :-\ Supongo que
debe haber algún problema en algún sitio, pero no parece que el paso de
parámetros sea el responsable. Por ejemplo:
In [41]: def f2(n,p): return n*p
....:
In [42]: timeit f2(2,10)
10000000 loops, best of 3: 166 ns per loop
In [43]: timeit f2(2.,10)
1000000 loops, best of 3: 179 ns per loop
o sea, que más o menos se tarda lo mismo en pasar un entero que un
número en coma flotante (como debe ser). Puede que el problema sea más
bien el método de medida, pero no lo tengo claro.
Más al hilo de la pregunta original, si se está interesado en efectuar
operaciones matemáticas de manera veloz, lo mejor es siempre acudir a
paquetes optimizados a tal efecto, como NumPy [1]. Un ejemplo:
In [44]: import numpy
In [45]: a = np.arange(1e6)
In [46]: timeit a**10
10 loops, best of 3: 141 ms per loop
Donde como se ve, se tarda unos 141 ms / 1e6 ~= 141 ns por elemento. Se
pueden obtener velocidades aún superiores con paquetes específicos como
numexpr [2], que se han optimizado para determinados rangos de valores.
Usando el ejemplo anterior:
In [47]: import numexpr
In [48]: timeit numexpr.evaluate("a**10")
100 loops, best of 3: 5.89 ms per loop
donde el tiempo queda reducido a unos 6 ns por elemento, lo cual es
realmente rápido.
[1] http://numpy.scipy.org
[2] http://code.google.com/p/numexpr
Saludos,
--
Francesc Alted
"One would expect people to feel threatened by the 'giant
brains or machines that think'. In fact, the frightening
computer becomes less frightening if it is used only to
simulate a familiar noncomputer."
-- Edsger W. Dykstra
"On the cruelty of really teaching computer science"
_______________________________________________
Lista de correo Python-es
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes
Más información sobre la lista de distribución Python-es