Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

Optimización en Python

Un espacio donde aprenderás algunos tips para optimizar código Python
by

Carlos Zager

on 5 November 2012

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Optimización en Python

Optimización en
Python por Carlos Zager Escribe el código
Pruébalo y ve si tiene el rendimiento deseado
Si es así, estas listo
Si no, prueba opcionalmente correrlo en PyPy
Haz "Profiling" para identificar las partes lentas
Modifica el código hasta que el rendimiento cumpla con las necesidades. Si es necesario reescribe las partes lentas en C (son de mucha ayuda los wrapper o interfaces SWIG, Pyrex, Boost) ¿Cuando debes optimizar en Python? Lo que verás a continuación NO es un paso a paso para mejorar tu código en Python
NO es una receta que aplique en todos los casos


SI es, un conjunto de Tips que suelen (en muchos casos) ofrecer un mejor rendimiento del código Python ¿Qué es y que no es esta presentación? Un profiler es un programa que describe el rendimiento y/o funcionamiento en vivo de un un programa, ofreciéndonos un conjunto de métricas y estadísticas sobre el mismo.

Python nos ofrece junto con sus librerías estándares 3 módulos: profile , cProfile y pstats.

Además de esto podemos conseguir el módulo line_profiler y kernprof.

Y por otro lado tenemos timeit que nos puede ayudar con las pruebas. ¿Pero cómo se come eso del "Profiling"? Supongamos que en nuestro ejemplo no hubiésemos tenido mil canciones sino solo una.
Pudimos haber escrito nuestro código como:


from ID3 import ID3
def f1(filename,genre):
info=ID3(filename)
return info.find_genre(genre)

if __name__=='__main__':
import timeit
print timeit.timeit("f1('ejemplo.mp3','Rock')",setup="from mp3s import f1",number=1000) Tomemos un ejemplo de la vida real... El proyecto ID3 de Ben Gertzfield permite leer información ID3 de archivos MP3

Si buscamos dentro del codigo de ID3.py (Ver 1.2) podemos ver que en la función find_genre (línea 288) se hizo uso de una sentencia "for" para el fin deseado.

Creamos un ejemplo sencillo (mp3s.py) para hacer el profiling

from ID3 import ID3
lista_mp3 #Es un conjunto de direcciones a archivos mp3
for x in lista_mp3:
info=ID3(x)
info.find_genre('Rock') Tomemos un ejemplo de la vida real... Ahora corremos python -m cProfile mp3s.py
para una lista de 1000 canciones esto podría verse parecido a Tomemos un ejemplo de la vida real... Los resultados aquí mostrados fueron realizados con una máquina cuyas especificaciones son:

Dell XPS L501X
Procesador Intel Core i5-480M 2.66GHz 3M
8 GB RAM DDR3
Ubuntu 12.04 LTS
Python 2.7.3rc2 [GCC 4.6.3]

En los casos donde así se especifique también se utilizó bajo el mismo ambiente

PyPy 1.9.0 [GCC 4.4.3] Especificaciones de pruebas def find_genre(self, genre_to_find):
i = 0
find_me = string.lower(genre_to_find)

for genre in self.genres:
if string.lower(genre) == find_me:
break
i = i + 1
if i == len(self.genres):
return -1
else:
return i Tomemos un ejemplo de la vida real... def find_genre(self,genre_to_find):
return self.genres.find( genre_to_find.title() ) Tomemos un ejemplo de la vida real... Pero que pasa cuando sabemos que función es la que corre lento, pero esta tiene muchas líneas de código y no identificamos donde esta el cuello de botella?

En estos casos usamos line_profiler y kernprof

Para ello colocamos el decorador @profile a la función que queremos evaluar, en este caso se la colocamos a strip_padding
dado que nos dimos cuenta que hay un exceso de llamadas a len

Luego corremos el comando

kernprof -l -v mp3s.py

si se desea consultar los resultados, luego se puede hacer
python -m line_profiler mp3s.py.lprof Tomemos un ejemplo de la vida real...
Podemos ver que hay un exceso de llamadas y del análisis podemos replantear la función como

def strip_paddings(s):
return s.replace('\x00','') Tomemos un ejemplo de la vida real... Tomemos un ejemplo de la vida real... podríamos apreciar estos resultados de mejor manera usando pstats Juntar strings Tips de optimización def f1(l):
s=''
for c in l:
s+=c
return s def f1(l):
return ''.join(l) def f2(l):
for c in l:
le(c) Copias locales de funciones def f2(l):
le=len
for c in l:
le(c) Tips de optimización Usar iteradores map(math.sqrt,xrange(100)) itertools.imap(math.sqrt,xrange(100)) Los iteradores se usan por defecto en Python 3 -92.78% En PyPy el map tuvo una reducción del 61.90% y el imap 98.08% frente a la corrida original Tips de optimización Usar generadores for i in A:
for j in B:
if i==j:
hacemos algo a=set(A)
b=set(B)
c=a.intersect(b)
itertools.imap(hacemos algo, c) def f3(l):
a=[]
al=algo
for i in l:
a.append(al(a))
return a def f3(l):
al=algo
for i in l:
yield al(i) Usar operaciones de conjuntos En vez de hacer S1+S2+S3 , hacer '%s%s%s'%(S1,S2,S3) * Tips de optimización def f4(l):
a=[]
for i in l:
a.insert(0,algo(i))
return a def f4(l):
a=[]
for i in l:
a.append(algo(i))
a.reverse()
return a Tomar en cuenta que hace nuestro algoritmo Inicializar diccionarios d = {}
for c in l:
if c not in d:
d[c] = 0
d[word] += 1 d = {}
for c in l:
try:
d[c] += 1
except KeyError:
d[c] = 1 Para visualizar grafos RunSnakeRun, Gprof2Dot o PyCallGraph Tips de optimización for i in l:
func_void(i) any( itertools.imap( func_void,l ) ) any esta implementado en C , por lo que toda la operación correrá bajo este contexto obtenido un alto incremento de velocidad Aprovechandonos de any Referencias http://www.python.org/doc/essays/list2str.html
http://wiki.python.org/moin/PythonSpeed/PerformanceTips
http://www.algorithm.co.il/blogs/computer-science/10-python-optimization-tips-and-issues/
http://docs.python.org/2/library/profile.html
http://docs.python.org/2/library/timeit.html
http://oreilly.com/python/excerpts/python-in-a-nutshell/testing-debugging.html
http://onlamp.com/pub/a/python/2005/12/15/profiling.html
http://www.dabeaz.com/generators/index.html
http://wiki.python.org/moin/Generators
http://packages.python.org/line_profiler/
http://pycallgraph.slowchop.com Preguntas ??? czager@zava.com.ve Octubre, 2012 http://zava.com.ve
Full transcript