Python Cython que es y por qué es más rápido que Python

Introducción

Cython es un lenguaje de programación que nos brinda la posibilidad de escribir extensiones en C para el lenguaje Python de forma tan fácil como programar en Python. Su principal objetivo es convertirse en un superconjunto del lenguaje Python, lo que significa una programación de alto nivel, orientada a objetos, funcional y dinámica.

Además de estas características, como parte del propio lenguaje, tiene soporte para declaraciones de tipos estáticos opcionales. El código generado se traduce a código optimizado en C/C++ y se compila como una extensión de Python (módulo).

Todo esto permite una ejecución muy rápida y una estrecha integración con las bibliotecas externas de C, manteniendo la alta productividad que Python proporciona al programador y por la que el lenguaje es mundialmente conocido.

En este post, voy a mostrar cómo integrar Python con Cython usando el ejemplo de un código muy simple para sumar números.

1. Instalación

Primero vamos a instalar el módulo Cython usando el comando:

pip install Cython
Python Cython instalación pip

Ya que los archivos generados con Cython es necesario compilarlos, debemos tener instalado el compilador GCC.

Para comprobarlo, ejecutamos el siguiente comando:

gcc --help
Ayuda del comando gcc

Si el comando no existe, debemos instalar el compilador GCC.

Algunos enlaces para instalarlo en diferentes sistemas operativos:

2. Código de ejemplo

Primero, creamos la versión en Python de la función generando un archivo llamado ejemplo_suma.py y añadimos el siguiente código que añade un número basándose en un rango de números:

def sumar_numero (num):
    resultado = 0
    for i in range(num):
      resultado += 1
    return resultado

A continuación, creamos otro archivo llamado ejemplo_suma_cy.pyx que es una traducción del anterior código Python al lenguaje Cython, tal y como se indica en la documentación:

cpdef sumar_numero(int num):
    cpdef int resultado = 0
    cpdef int i
    for i in range (num):
        resultado += 1
    return resultado

3. Compilación del código generado

Una vez que tenemos el archivo creado, debemos generar otro archivo en Python para realizar la instalación del módulo que acabamos de crear, para de esta forma poderlo importar directamente desde nuestro código en Python.

El objetivo final es compilar elcódigo Cython en un archivo .so que es una biblioteca cargada dinámicamente por el sistema operativo.

from setuptools import setup
from Cython.Build import cythonize

setup (
     ext_modules = cythonize("ejemplo_suma_cy.pyx")
)

Para generar el objeto .so , ejecutamos el siguiente comando:

python setup.py build_ext --inplace

Si el anterior comando genera un error «ejemplo_suma.c:18:10: fatal error: Python.h: Nosuch file or directory» debemos instalar los ficheros de cabecera para la compilación de extensiones en Python. En este enlace podemos instalar las librerías necesarias en la distribución Linux Ubuntu.

Si la compilación ha funcionado correctamente, tendremos la siguiente estructura de ficheros:

Compilación con python cython extension

Como podemos ver, se ha generado el archivo .so que contiene todo el código de la función escrita en Cython.

4. Test de la función creada en Cython

Para testear la función que hemos creado, vamos a crear un nuevo archivo llamado test_ejemplo_cy.py en el que añadiremos el siguiente código para poder llamar a la función:

import ejemplo_suma_cy

if __name__ == '__main__':
    res = ejemplo_suma_cy.sumar_numero(6_000_000)
    print(res)

Antes de comprobar los resultados, vamos a crear otro archivo Python llamado test_rendimiento_funcion.py que nos mostrará el rendimiento de las dos funciones.

De esta forma podremos ver la diferencia entre la versión escrita en Python y la que hemos creado en Cython:

import timeit

if __name__ == "__main__":

    archivo_py = timeit.timeit("ejemplo_suma.sumar_numero(5000)", setup="import ejemplo_suma",number = 10_0)

    archivo_cy = timeit.timeit("ejemplo_suma_cy.sumar_numero(5000)",setup= "import ejemplo_suma_cy",number)

    print(archivo_py,archivo_cy)
    print("Cython es {}x veces más rapido que Python".format(archivo_py/archivo_cy))

Al ejecutar el test de rendimiento obtenemos los siguientes resultados:

Resultados prueba de ejecución python cython

5. Conclusión

Como hemos podido comprobar, la función escrita en Cython es 3078 veces más rápida que la misma función escrita en Python.

Cython es la solución ideal cuando es necesario optimizar el rendimiento de ciertas partes de nuestro código o cuando necesitamos llamar a bibliotecas o funciones escritas en el lenguaje C.

Si te ha interesado este artículo, te aconsejo que uses Docker para todas tus pruebas. Este artículo puede ayudarte a instalar Docker en Ubuntu 20.04.

Enlaces y vídeos de interés

Vídeos


LinkedIn

comments powered by Disqus