¿Por qué los programas de Python a menudo son más lentos que el programa equivalente escrito en C o C++?
python es lento (8)
Aparte de las respuestas ya publicadas, una cosa es la capacidad de los pitones para cambiar cosas en tiempo de ejecución que no puede cambiar, por ejemplo, C. Puede agregar funciones de miembro a las clases a medida que avanza. Además, la naturaleza dinámica de los pitones hace que sea imposible decir qué tipo de parámetros se pasarán a una función, lo que a su vez hace que la optimización sea mucho más difícil.
RPython parece ser una forma de solucionar el problema de optimización.
Sin embargo, es probable que no esté cerca del rendimiento de C para el aumento de peso y similares.
¿Por qué Python parece más lento, en promedio, que C / C ++? Aprendí Python como mi primer lenguaje de programación, pero recién comencé con C y ya siento que puedo ver una clara diferencia.
C y C ++ se compilan en código nativo, es decir, se ejecutan directamente en la CPU. Python es un lenguaje interpretado, lo que significa que el código Python que escribes debe pasar por muchas, muchas etapas de abstracción antes de que pueda convertirse en código de máquina ejecutable.
CPython es particularmente lento porque no tiene un optimizador Just in Time (ya que es la implementación de referencia y elige la simplicidad sobre el rendimiento en ciertos casos). Unladen Swallow es un proyecto para agregar un JIT respaldado por LLVM en CPython, y logra aceleraciones masivas. Es posible que Jython y IronPython sean mucho más rápidos que CPython y que estén respaldados por máquinas virtuales altamente optimizadas (JVM y .NET CLR).
Sin embargo, una cosa que posiblemente dejará a Python más lento, es que se escribe dinámicamente, y hay toneladas de búsquedas para cada atributo de acceso.
Por ejemplo, llamar a f
en un objeto A
causará posibles búsquedas en __dict__
, llamadas a __getattr__
, etc., y finalmente, llamar a __call__
en el objeto llamable f
.
Con respecto a la tipificación dinámica, hay muchas optimizaciones que se pueden hacer si sabe con qué tipo de datos está tratando. Por ejemplo, en Java o C, si tiene una matriz directa de enteros que desea sumar, el código de ensamblaje final puede ser tan simple como obtener el valor en el índice i
, agregarlo al accumulator
y luego incrementar i
.
En Python, esto es muy difícil hacer que el código sea óptimo. Digamos que tienes un objeto de subclase de lista que contiene int
s. Antes de agregar cualquiera, Python debe llamar a la list.__getitem__(i)
, luego agregarlo al "acumulador" llamando al accumulator.__add__(n)
, luego repetir. Aquí pueden suceder toneladas de búsquedas alternativas porque es posible que otro hilo haya cambiado, por ejemplo, el método __getitem__
, el dict de la instancia de la lista o el dict de la clase, entre llamadas para agregar o obtener un ítem. Incluso encontrar el acumulador y la lista (y cualquier variable que esté usando) en el espacio de nombres local provoca una búsqueda de dictado. Esta misma sobrecarga se aplica cuando se usa cualquier objeto definido por el usuario, aunque para algunos tipos incorporados, es algo mitigado.
También vale la pena señalar que los tipos primitivos como bigint (int en Python 3, long en Python 2.x), list, set, dict, etc, etc., son lo que la gente usa mucho en Python. Hay toneladas de operaciones integradas en estos objetos que ya están lo suficientemente optimizadas. Por ejemplo, para el ejemplo anterior, simplemente llamaría sum(list)
lugar de usar un acumulador e índice. Siguiendo estos y un poco de procesamiento de números con int / float / complex, por lo general no tendrá problemas de velocidad, y si lo hace, es probable que haya una unidad crítica de tiempo pequeño (una función de resumen de SHA2, por ejemplo) que pueda simplemente muévase a C (o código Java, en Jython). El hecho es que cuando codifica C o C ++, va a perder mucho tiempo haciendo cosas que puede hacer en unos pocos segundos / líneas de código Python. Yo diría que la compensación siempre vale la pena, excepto en los casos en los que está haciendo algo como programación integrada o en tiempo real y no puede pagarla.
La comparación de C / C ++ con Python no es una comparación justa. Como comparar un coche de carreras de F1 con un camión utilitario.
Lo que sorprende es lo rápido que Python es en comparación con sus compañeros de otros lenguajes dinámicos. Si bien la metodología a menudo se considera defectuosa, mire The Computer Language Benchmark Game para ver la velocidad relativa del lenguaje en algoritmos similares.
La comparación con Perl, Ruby y C # son más "justas"
La compilación frente a la interpretación no es importante aquí: Python se compila, y es una pequeña parte del costo de tiempo de ejecución para cualquier programa no trivial.
Los costos principales son: la falta de un tipo de entero que corresponde a los enteros nativos (lo que hace que todas las operaciones de enteros sean mucho más caras), la falta de tipificación estática (lo que dificulta la resolución de los métodos y significa que los tipos de valores se deben verificar) en tiempo de ejecución), y la falta de valores sin caja (que reducen el uso de la memoria y pueden evitar un nivel de direccionamiento indirecto).
No es que cualquiera de estas cosas no sea posible o no se pueda hacer más eficiente en Python, pero se ha optado por favorecer la conveniencia y la flexibilidad del programador, y la limpieza del idioma en lugar de la velocidad de ejecución. Algunos de estos costos pueden superarse con una compilación inteligente de JIT, pero los beneficios que proporciona Python siempre tendrán un costo.
La diferencia entre python y C es la diferencia usual entre un lenguaje interpretado (bytecode) y compilado (a nativo). Personalmente, realmente no veo a python como lento, se maneja bien. Si intentas usarlo fuera de su ámbito, por supuesto, será más lento. Pero para eso, puedes escribir extensiones C para python, que colocan algoritmos de tiempo crítico en el código nativo, haciéndolo mucho más rápido.
Python es un lenguaje de nivel superior al C, lo que significa que le extrae los detalles de la computadora: administración de memoria, punteros, etc., y le permite escribir programas de una manera más cercana a como piensan los humanos.
Es cierto que el código C generalmente se ejecuta de 10 a 100 veces más rápido que el código Python si solo mide el tiempo de ejecución. Sin embargo, si también incluye el tiempo de desarrollo, Python a menudo supera C. Para muchos proyectos, el tiempo de desarrollo es mucho más crítico que el rendimiento en tiempo de ejecución. Un tiempo de desarrollo más largo se convierte directamente en costos adicionales, menos funciones y un tiempo de comercialización más lento.
Internamente, la razón por la que el código Python se ejecuta más lentamente es porque el código se interpreta en tiempo de ejecución en lugar de compilarse en código nativo en tiempo de compilación.
Otros lenguajes interpretados, como Java bytecode y .NET bytecode, se ejecutan más rápido que Python porque las distribuciones estándar incluyen un compilador JIT que compila bytecode a código nativo en tiempo de ejecución. La razón por la cual CPython ya no tiene un compilador JIT es porque la naturaleza dinámica de Python hace que sea difícil escribir uno. Hay work en progress para escribir un tiempo de ejecución de Python más rápido, por lo que debe esperar que la brecha de rendimiento se reduzca en el futuro, pero probablemente pasará un tiempo antes de que la distribución estándar de Python incluya un potente compilador JIT.
Python se implementa normalmente como un lenguaje de scripting. Eso significa que pasa por un intérprete, lo que significa que traduce el código sobre la marcha al lenguaje de máquina en lugar de tener el ejecutable todo en lenguaje de máquina desde el principio. Como resultado, tiene que pagar el costo de traducir el código además de ejecutarlo. Esto es cierto incluso para CPython, aunque se compila a bytecode que está más cerca del lenguaje de la máquina y, por lo tanto, se puede traducir más rápido. Con Python también se incluyen algunas características de tiempo de ejecución muy útiles, como la escritura dinámica, pero estas cosas normalmente no se pueden implementar incluso en las implementaciones más eficientes sin costos de tiempo de ejecución elevados.
Si está realizando un trabajo muy intensivo con el procesador, como escribir sombreadores, no es raro que Python esté 200 veces más lento que C ++. Si usas CPython, ese tiempo puede reducirse a la mitad, pero todavía no es tan rápido. Con todas esas golosinas runtmie viene un precio. Hay muchos puntos de referencia para mostrar esto y here''s uno particularmente bueno. Según lo admitido en la primera página, los puntos de referencia son defectuosos. Todos son enviados por usuarios que hacen todo lo posible para escribir código eficiente en el idioma de su elección, pero le da una buena idea general.
Le recomiendo que intente mezclar los dos juntos si le preocupa la eficiencia: entonces puede obtener lo mejor de ambos mundos. Principalmente soy programador de C ++, pero creo que muchas personas tienden a codificar demasiado el código mundano de alto nivel en C ++ cuando es solo una molestia hacerlo (compilar los tiempos como un solo ejemplo). Mezclar un lenguaje de scripting con un lenguaje eficiente como C / C ++ que está más cerca del metal es realmente el camino a seguir para equilibrar la eficiencia del programador (productividad) con la eficiencia del procesamiento.