real - matplotlib python
Equivalencia de Python con funciones en lĂnea o macros (5)
Me acabo de dar cuenta de que haciendo
x.real*x.real+x.imag*x.imag
es tres veces más rápido que hacer
abs(x)**2
donde x es una matriz numpy de números complejos. Para la legibilidad del código, podría definir una función como
def abs2(x):
return x.real*x.real+x.imag*x.imag
que todavía es mucho más rápido que abs (x) ** 2, pero es a costa de una llamada a función. ¿Es posible alinear tal función, como lo haría en C usando macro o usando palabra clave en línea?
¿Es posible alinear tal función, como lo haría en C usando macro o usando palabra clave en línea?
No. Antes de llegar a esta instrucción específica, los intérpretes de Python ni siquiera saben si existe tal función, mucho menos lo que hace.
Como se señala en los comentarios, PyPy se alineará automáticamente (lo anterior aún se mantiene; "simplemente" genera una versión optimizada en tiempo de ejecución, se beneficia de ella, pero se rompe cuando se invalida), aunque en este caso específico eso no ayuda. ya que la implementación de NumPy en PyPy comenzó hace poco y ni siquiera es un nivel beta hasta el día de hoy. Pero la conclusión es: no se preocupe por las optimizaciones en este nivel en Python. O las implementaciones lo optimizan o no lo hacen, no es su responsabilidad.
En realidad, podría ser incluso más rápido de calcular, como:
x.real** 2+ x.imag** 2
Por lo tanto, es probable que disminuya el costo adicional de la llamada a la función. Veamos:
In []: n= 1e4
In []: x= randn(n, 1)+ 1j* rand(n, 1)
In []: %timeit x.real* x.real+ x.imag* x.imag
10000 loops, best of 3: 100 us per loop
In []: %timeit x.real** 2+ x.imag** 2
10000 loops, best of 3: 77.9 us per loop
Y encapsulando el cálculo en una función:
In []: def abs2(x):
..: return x.real** 2+ x.imag** 2
..:
In []: %timeit abs2(x)
10000 loops, best of 3: 80.1 us per loop
De todos modos (como otros han señalado) este tipo de micro-optimización (para evitar una llamada a la función) no es realmente una forma productiva de escribir el código python.
Estoy de acuerdo con todos los demás en que tales optimizaciones solo te causarán dolor en CPython , que si te importa el rendimiento deberías considerar PyPy (aunque nuestro NumPy puede ser demasiado incompleto para ser útil). Sin embargo, no estoy de acuerdo y digo que puede preocuparse por tales optimizaciones en PyPy, no específicamente porque PyPy lo hace automáticamente, pero si conoce bien PyPy, puede sintonizar su código para hacer que PyPy emita el ensamblado que desee. no es que necesites casi nunca.
No es exactamente lo que el OP ha pedido, pero está cerca:
Inliner enlista las llamadas a la función de Python. Prueba de concepto para esta publicación de blog
from inliner import inline @inline def add_stuff(x, y): return x + y def add_lots_of_numbers(): results = [] for i in xrange(10): results.append(add_stuff(i, i+1))
En el código anterior, la función add_lots_of_numbers se convierte en esto:
def add_lots_of_numbers(): results = [] for i in xrange(10): results.append(i + i + 1)
También cualquier persona interesada en esta pregunta y las complicaciones involucradas en la implementación de dicho optimizador en CPython, también pueden desear echar un vistazo a:
No.
Lo más cerca que puede llegar a las macros C es una secuencia de comandos (awk u otra) que puede incluir en un archivo MAKE, y que sustituye un determinado patrón como ABS (x) ** 2 en sus scripts Python con la forma larga.