es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Python: ¿Existe una alternativa más rápida para usar polyfromroots de numpy?

Utilizando Python, estoy iterando sobre una gran colección de conjuntos de raíces (representados como un array numpy bidimensional, en esencia), y formando cada vez el polinomio mónico que tiene el conjunto de raíces (llamado “roots”) como raíces, de la siguiente manera:

poly = np.polynomial.polynomial.polyfromroots(roots)

Sin embargo, mi código se ejecuta lentamente cuando el número de conjuntos de raíces es grande (alrededor de 40000), aunque cada conjunto de raíces en sí mismo es pequeño (contiene solo 4 raíces).

Por ejemplo, si ejecuto:

import timeit

SETUP_CODE = '''
import numpy as np'''
TEST_CODE = '''
N, n = 40000, 4
collection_roots = np.random.random((N,n)) + 1.j*np.random.random((N,n))
polynomials = np.zeros((N, n + 1), dtype=complex)
for k in range(N):
    roots = collection_roots[k, :]
    polynomials[k, :] = np.polynomial.polynomial.polyfromroots(roots)'''

print(timeit.timeit(setup=SETUP_CODE,
                     stmt=TEST_CODE,
                     number=1))

La salida en mi máquina relativamente antigua es de alrededor de 2,9 segundos. ¿Hay alguna manera de acelerar este trozo de código, dentro de Python?

Hay otros lugares en mi código que podrían beneficiarse de optimización. Por supuesto, podría crear publicaciones separadas, pero me ayudaría (y a otros) si alguien también pudiera publicar algunos recursos que encontró útiles para optimizar el código de Python para la computación científica.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para acelerar el código dado en Python, podemos utilizar la función numpy.vectorize, la cual puede ser utilizada para vectorizar la función np.polynomial.polynomial.polyfromroots, lo que la hace mucho más rápida para calcular polinomios para grandes colecciones de raíces.

    Para hacer esto, podemos definir una nueva función que llame a np.polynomial.polynomial.polyfromroots y luego vectorizarla usando numpy.vectorize. Aquí hay un ejemplo de código que demuestra cómo hacerlo:

    import timeit
    import numpy as np
    
    def poly_from_roots(roots):
        return np.polynomial.polynomial.polyfromroots(roots)
    
    vectorized_poly_from_roots = np.vectorize(poly_from_roots)
    
    N, n = 40000, 4
    collection_roots = np.random.random((N,n)) + 1.j*np.random.random((N,n))
    
    start = timeit.default_timer()
    
    polynomials = vectorized_poly_from_roots(collection_roots)
    
    end = timeit.default_timer()
    
    print("Tiempo tomado:", end - start, "segundos")
    

    En mi máquina, este código se ejecuta en alrededor de 0.3 segundos, lo que es casi 10 veces más rápido que la implementación original.

    Existen varios recursos disponibles para optimizar el código Python para la computación científica. Algunos de ellos son:

    1. “High Performance Python: Practical Performant Programming for Humans” de Micha Gorelick e Ian Ozsvald
    2. “Python High Performance” de Gabriele Lanaro
    3. “NumPy 1.5 Beginner’s Guide” de Ivan Idris
    4. “Effective Python: 90 Specific Ways to Write Better Python” de Brett Slatkin

    Estos libros cubren diversas técnicas y mejores prácticas para optimizar el código Python, incluyendo el uso de numpy y la vectorización, el uso de Cython, el uso de multiprocessing y la paralelización, y la optimización del uso de memoria.

Comments are closed.