mandelbrot00

Hay dos clases de lenguajes, los que se compilan -es decir, se transforman en código binario, ejecutable, que entiende la computadora- y los interpretados, que analizan cada instrucción, ven si existe y la ejecutan. Si el programa regresa a una instrucción que ya se ejecutó, de nuevo el intérprete debe analizarla para ver si la puede ejecutar. Son estos últimos programas mucho más lentos que sus contrapartes compiladas.

Pero, ¿qué tan lento será Python, lenguaje de moda incluso en la Facultad de Ciencias de la UNAM? Para poder probar su velocidad se requiere de alguna prueba reconocida, un “benchmark”, una cama de diferentes pruebas de programas, midiendo el tiempo que tardan en llegar a un resultado previsto. Por ejemplo, el cálculo del conjunto de Mandelbrot, que requiere de muchos cálculos matemáticos, es un buen benchmark pues es fácilmente comparable en diferentes implementaciones de los lenguajes de programación.

Jean Francois Puget, un ingeniero de software de IBM, decidió usar este objeto matematico para probar la velocidad de Python contra lenguajes más tradicionales. Empezó el investigador con una pueba “ingenua” – naive, en Python un triple loop anidado que hace scan x y scan y, e itera la función. Esto en Python es unas 70 veces más lento que el mismo código pero en C. El código en Python usa listas para guardar los resultados, por lo que la siguiente “optimización” que se hizo fue cambiar las listas por arreglos de números (Numpy) y con loops explícitos. Esto resultó incluso más lento, como unas 110 veces más lento que C aún usando estructuras de datos como los arreglos, lo cual es muy simple de hacer en cualquier lenguaje en donde uno esperaría las cosas fuesen más rápidas por ello.

Para poder tener arreglos que sean veloces en Python se requiere compilar el código y por suerte Numba, un compilador JIT (Just In Time), así como Cython, ambos convirtieron el programa en tiempo comparable a los tiempos medidos en los programas en C. La conclusión parece obvia: no es el lenguaje el problema, sino la forma en que ha sido implementado. Si se tiene un buen compilador entonces el lenguaje que se deseé puede ser tan bueno como usar C, el cual mucha gente ve como una especie de ensamblador de bajo nivel e independiente de la plataforma.

Una pregunta que hace el investigador Puget es si los lenguajes pueden acelerarse usando abstracciones avanzadas que saquen ventaja del hardware. Por ejemplo, ¿podría la vectorización sacar ventaja de los tipos dd operaciones SIMD para hacer que las cosas corrieran más rápido que un programa secuencial de C? Si la vectorización se da, la respuesta es que sí, mejora las cosas pero no mucho, pues es solamente unas tres veces más lento que el C secuencial. Es mejor que la versión no-vectorizada en todo caso.

También se puede intentar usar herramientas fuera del lenguaje, como TensorFlow, de Google, que puede usarse para vectorizar los cálculos. Usando solamente el CPU, TensorFlow tiene más o menos la misma velocidad que los programas vectorizados (Numpy) y son unas 3 veces más lentos nada más. Hay además la opción de usar los GPUs. Por ejemplo, si se usa PyOpenCL y PyCUDA para tener acceso directo al GPU, hallaremos que el programa en Python corre unas 15 veces más rápido que el programa secuencial de C. Cambiando una sola instrucción en el código en Python para usar estas bibliotecas de paralelismo, pueden desempeñar las funciones unas 3.5 veces más

Así entonces, Python puro es lento comparado con el C simple y se requiere de un compilador para que corra más rápido. Si se quiere ir más rápido que C, entonces se necesita mover el código a los GPUs y esto se puede hacer desde un enfoque de alto nivel.

Referencias:

How To Quickly Compute The Mandelbrot Set In Python 
i-programmer