Introducción a PyPy

0 acciones
0
0
0
0

Introducción

El lenguaje de programación Python es una interfaz que se puede implementar de muchas maneras diferentes. Algunos ejemplos incluyen CPython, que usa el lenguaje C; Jython, que se implementa con Java; etc.

A pesar de ser el más popular, CPython no es el más rápido. PyPy es una implementación alternativa de Python compatible y rápida. PyPy se basa en la compilación JIT, lo que reduce drásticamente el tiempo de ejecución de operaciones de larga duración.

En este tutorial, presentaremos PyPy para principiantes y destacaremos sus diferencias con CPython. También analizaremos sus ventajas y limitaciones. Después, veremos cómo descargar y usar PyPy para ejecutar un script sencillo de Python.

En concreto, esta formación cubre lo siguiente:

  • Una descripción general rápida de CPython
  • Introducción a PyPy y sus características
  • Limitaciones de PyPy
  • Ejecutando PyPy en Ubuntu
  • Tiempo de ejecución de PyPy vs. CPython

Una descripción general rápida de CPython

Antes de hablar de PyPy, es importante comprender cómo funciona CPython. A continuación, se muestra una imagen del flujo de ejecución de un script de Python implementado con CPython.

Dado un script de Python .py, el código fuente se compila primero en bytecode mediante el compilador CPython. El bytecode se genera y se almacena en un archivo con la extensión pyc. Posteriormente, se ejecuta en un entorno virtual mediante el intérprete de CPython.

Usar un compilador para convertir el código fuente a código de bytes tiene sus ventajas. Si no se usa un compilador, el intérprete trabaja directamente con el código fuente y lo traduce línea por línea a código máquina. La desventaja es que se deben aplicar procesos para traducir cada línea de código fuente a código máquina, y estos procesos se repiten para cada línea. Por ejemplo, el análisis sintáctico se aplica a cada línea independientemente de las demás, por lo que el intérprete dedica mucho tiempo a traducir el código. El compilador soluciona este problema porque puede procesar todo el código a la vez, por lo que el análisis sintáctico se aplica solo una vez en lugar de para cada línea de código. De esta manera, el código de bytes generado por el compilador se interpreta fácilmente. Tenga en cuenta que compilar todo el código fuente puede no ser útil en algunos casos, y veremos un claro ejemplo de esto al hablar de PyPy.

Una vez generado el bytecode, el intérprete que se ejecuta en la máquina virtual lo ejecuta. El entorno virtual es beneficioso porque desacopla el bytecode de CPython de la máquina, lo que permite que Python sea multiplataforma.

Desafortunadamente, usar un compilador para generar código de bytes no es suficiente para acelerar la ejecución de CPython. El intérprete funciona traduciendo el código a código máquina cada vez que se ejecuta. Por lo tanto, si una línea tarda LX segundos en ejecutarse, ejecutarla 10 veces costará X*10 segundos. Para operaciones de larga duración, esto implica un alto consumo de tiempo de ejecución.

Basándonos en los errores de CPython, ahora echemos un vistazo a PyPy.

Introducción a PyPy y sus características

PyPy es una implementación de Python similar a CPython, compatible y rápida. "Compatible" significa que PyPy es compatible con CPython, lo que permite usar casi todos los comandos de CPython en PyPy. Como se mencionó aquí, existen algunas diferencias de compatibilidad. La mayor ventaja de PyPy es su velocidad. PyPy es mucho más rápido que CPython. Más adelante veremos algunas pruebas en las que PyPy funciona aproximadamente 7 veces más rápido. En algunos casos, incluso puede ser decenas o cientos de veces más rápido que CPython. Entonces, ¿cómo logra PyPy su velocidad?

Velocidad

PyPy utiliza un compilador justo a tiempo (JIT) que puede acelerar drásticamente los scripts de Python. El tipo de compilación utilizado en CPython es adelantado en el tiempo (AOT), lo que significa que todo el código se traduce a bytecode antes de su ejecución. El JIT solo traduce el código en tiempo de ejecución, solo cuando es necesario.

El código fuente puede contener bloques de código que no se ejecutan en absoluto, pero que se traducen mediante el compilador AOT. Esto resulta en tiempos de procesamiento más lentos. Cuando el código fuente es extenso y contiene miles de líneas, usar JIT marca una gran diferencia. Con AOT, se traduce todo el código fuente, lo que requiere mucho tiempo. Con JIT, solo se ejecutan las partes necesarias del código, lo que lo hace mucho más rápido.

Después de que PyPy traduce un fragmento de código, este se almacena en caché. Esto significa que el código se traduce solo una vez y se utiliza posteriormente. El intérprete de CPython repite la traducción cada vez que se ejecuta el código, lo cual es otra razón de su lentitud.

Fácil

PyPy no es la única forma de mejorar el rendimiento de los scripts de Python, pero es la más sencilla. Por ejemplo, Cython puede usarse para acelerar la asignación de tipos de C a variables. El problema es que Cython requiere que el desarrollador revise y optimice manualmente el código fuente. Esto es tedioso y aumenta su complejidad a medida que aumenta el tamaño del código. Al usar PyPy, se ejecuta código Python normal mucho más rápido y sin esfuerzo.

Sin pila

Python estándar utiliza la pila de C. Esta pila almacena la secuencia de funciones que se invocan entre sí (retornos). Dado que la pila tiene un tamaño limitado, el número de llamadas a funciones está limitado.

PyPy usa Stackless Python, una implementación de Python que no utiliza la pila de C. En su lugar, almacena las llamadas a funciones en la pila junto con los objetos. El tamaño de la pila es mayor que el del montón, lo que permite realizar más llamadas a funciones.

Python sin pila también admite microhilos, que son mejores que los hilos de Python normales. En un hilo de Python sin pila, se pueden ejecutar miles de tareas llamadas "tasklets", todas ejecutándose en un solo hilo.

El uso de tasklets permite ejecutar tareas simultáneamente. La concurrencia significa que dos tareas se ejecutan simultáneamente y comparten los mismos recursos. Una tarea se ejecuta durante un tiempo y luego se detiene para dar paso a la segunda. Cabe destacar que esto es diferente del paralelismo, que implica ejecutar dos tareas independientes pero simultáneas.

El uso de Tasklets reduce la cantidad de subprocesos creados, lo que reduce la sobrecarga que supone la gestión de todos estos subprocesos por parte del sistema operativo. Como resultado, acelerar la ejecución alternando entre dos subprocesos requiere más tiempo que alternar entre dos tareas.

El uso de Stackless Python también sentó las bases para las continuaciones. Estas permiten guardar el estado de una tarea y restaurarlo posteriormente para continuarla. Cabe destacar que Stackless Python no se diferencia del Python estándar. Simplemente añade más funcionalidad. Todo lo disponible en Python estándar también estará disponible en Stackless Python.

Después de discutir los beneficios de PyPy, hablemos de sus limitaciones en la siguiente sección.

Limitaciones de PyPy

Si bien puedes usar CPython en cualquier máquina y cualquier arquitectura de CPU, PyPy tiene un soporte relativamente limitado.

Aquí están las arquitecturas de CPU soportadas y mantenidas por PyPy (fuente):

  • x86 (IA-32) y x86_64
  • Plataformas ARM (ARMv6 o ARMv7, con VFPv3)
  • AArch64
  • PowerPC de 64 bits, tanto little endian como big endian
  • Sistema Z (s390x)

PyPy no funciona en todas las distribuciones de Linux, por lo que debe asegurarse de usar una de las distribuciones compatibles. Ejecutar el binario de PyPy para Linux en una distribución no compatible devolverá un error. PyPy solo es compatible con las versiones de Python 2 y Python 3: PyPy 2.7 y PyPy 3.6.

Si el código que se ejecuta en PyPy es Python puro, la aceleración que ofrece PyPy suele ser significativa. Sin embargo, si el código incluye extensiones de C como NumPy, PyPy puede incluso aumentar el tiempo. El proyecto PyPy se encuentra en desarrollo activo y, por lo tanto, podría ofrecer un mejor soporte para las extensiones de C en el futuro.

PyPy no es compatible con varios frameworks populares de Python, como Kivy. Kivy permite ejecutar CPython en todas las plataformas, incluyendo Android e iOS. Esto significa que PyPy no puede ejecutarse en dispositivos móviles.

Ahora que hemos visto las ventajas y limitaciones de PyPy, expliquemos cómo ejecutar PyPy en Ubuntu.

Ejecutando PyPy en Ubuntu

Puedes ejecutar PyPy en Mac, Linux o Windows, pero hablaremos sobre su ejecución en Ubuntu. Es importante tener en cuenta que los binarios de PyPy para Linux solo son compatibles con distribuciones de Linux específicas. Puedes consultar los binarios de PyPy disponibles y sus distribuciones compatibles en esta página. Por ejemplo, PyPy (o Python 2.7 o Python 3.6) solo es compatible con tres versiones de Ubuntu: 18.04, 16.04 y 14.04. Si tienes la última versión de Ubuntu (19.10), no podrás ejecutar PyPy en ella. Intentar ejecutar PyPy en una distribución no compatible mostrará este error:

Los binarios de PyPy vienen como archivos comprimidos. Solo tienes que descomprimir el archivo que descargaste. Dentro de la carpeta descomprimida hay una carpeta llamada bin donde se encuentra el archivo ejecutable de PyPy. Uso Python 3.6, por lo que el archivo se llama pypy3. En Python 2.7, simplemente se llama pypy.

Para CPython, si desea ejecutar Python 3 desde la terminal, simplemente introduzca el comando python3. Para ejecutar PyPy, simplemente ejecute el comando pypy3.

Como se muestra en la siguiente figura, al introducir el comando pypy3 en la terminal, es posible que aparezca el mensaje "pypy3" no encontrado. Esto se debe a que la ruta de acceso de PyPy no se ha añadido a la variable de entorno PATH. El comando que realmente funciona es ./pypy3, dado que la ruta actual en la terminal se encuentra dentro del directorio bin de PyPy. El punto . se refiere al directorio actual y se añade la barra / para acceder a algún elemento del directorio actual. Al ejecutar el comando ./pypy3, Python se ejecuta correctamente.

Ahora puedes trabajar con Python como siempre, aprovechando PyPy. Por ejemplo, podemos crear un script simple de Python que sume 1000 números y ejecutarlo con PyPy. El código es el siguiente.

nums = range(1000)
sum = 0
for k in nums:
sum = sum + k
print("Sum of 1,000 numbers is : ", sum)

Si este script se llama test.py, puedes simplemente ejecutarlo usando el siguiente comando (asumiendo que el archivo Python está ubicado dentro de la carpeta bin de PyPy, que es la misma ubicación que el comando pypy3).

./pypy3 test.py

La siguiente figura muestra el resultado de ejecutar el código anterior.

Tiempo de ejecución de PyPy vs. CPython

Para comparar el tiempo de ejecución de PyPy y CPython para la suma de 1000 números, el código para medir el tiempo cambia de la siguiente manera.

import time
t1 = time.time()
nums = range(1000)
sum = 0
for k in nums:
sum = sum + k
print("Sum of 1,000 numbers is : ", sum)
t2 = time.time()
t = t2 - t1
print("Elapsed time is : ", t, " seconds")

Para PyPy, el tiempo es cercano a 0,00045 segundos, en comparación con los 0,0002 segundos de CPython (ejecuté el código en mi máquina Core i7-6500U a 2,5 GHz). En este caso, CPython tarda menos que PyPy, lo cual es previsible, ya que no se trata de una tarea de larga duración. Si el código añadiera un millón de números en lugar de 1000, PyPy ganaría. En este caso, PyPy tardaría 0,00035 segundos y CPython 0,1 segundos. La ventaja de PyPy es ahora evidente. Esto debería darte una idea de lo lento que es CPython para tareas de larga duración.

Resultado

Este tutorial presenta PyPy, la implementación más rápida de Python. Su principal ventaja es su compilación justo a tiempo (JIT), que almacena en caché el código máquina compilado para evitar que se vuelva a ejecutar. También se destacan sus limitaciones, la principal de las cuales es que funciona bien con código Python puro, pero no es eficiente con extensiones de C.

También vimos cómo se ejecuta PyPy en Ubuntu y comparamos los tiempos de ejecución de CPython y PyPy, destacando el rendimiento de PyPy en tareas de larga duración. Mientras tanto, CPython aún podría superar a PyPy en tareas de corta duración. Exploraremos más comparaciones entre PyPy, CPython y Cython en próximos artículos.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

También te puede gustar