Escribí el siguiente script para probar la velocidad de la funcionalidad de clasificación de Python:
from sys import stdin, stdout
lines = list(stdin)
lines.sort()
stdout.writelines(lines)
Luego comparé esto con el sort
comando coreutils en un archivo que contiene 10 millones de líneas:
$ time python sort.py <numbers.txt >s1.txt
real 0m16.707s
user 0m16.288s
sys 0m0.420s
$ time sort <numbers.txt >s2.txt
real 0m45.141s
user 2m28.304s
sys 0m0.380s
El comando incorporado usó las cuatro CPU (Python solo usó una) pero tardó aproximadamente 3 veces más en ejecutarse. ¿Lo que da?
Estoy usando Ubuntu 12.04.5 (32 bits), Python 2.7.3 y sort
8.13
--buffer-size
para especificar quesort
use toda la memoria física disponible y ver si eso ayuda?Respuestas:
El comentario de Izkata reveló la respuesta: comparaciones específicas de la localidad. El
sort
comando usa la configuración regional indicada por el entorno, mientras que Python tiene por defecto una comparación de orden de bytes. Comparar cadenas UTF-8 es más difícil que comparar cadenas de bytes.Qué hay sobre eso.
fuente
locale.strxfrm
para ordenar, el script tardó ~ 32 segundos, aún más rápidosort
pero mucho menos.cut
, y otros también. En varias máquinas que ahora tengoexport LC_ALL=C
en.bashrc
. Pero cuidado: esto esencialmente se rompewc
(exceptowc -l
), solo por nombrar un ejemplo. Los "bytes incorrectos" no se cuentan en absoluto ...grep
: puede obtener una mejora sustancial en el rendimiento al agrupar archivos de gran tamaño deshabilitando UTF-8, especialmente cuando se hacegrep -i
Esto es más un análisis adicional que una respuesta real, pero parece variar según los datos que se ordenan. Primero, una lectura base:
OK, Python es mucho más rápido. Sin embargo, puede hacer que los coreutils sean
sort
más rápidos diciéndole que ordene numéricamente:Eso es mucho más rápido, pero Python aún gana por un amplio margen. Ahora, intentemos de nuevo pero con una lista no ordenada de números 1M:
Coreutils
sort -n
es más rápido para datos numéricos sin clasificar (aunque es posible que pueda modificar elcmp
parámetro de ordenación de Python para hacerlo más rápido). Coreutilssort
sigue siendo significativamente más lento sin la-n
bandera. Entonces, ¿qué pasa con los caracteres aleatorios, no con los números puros?Python aún supera a los coreutils pero por un margen mucho menor que el que muestra en su pregunta. Sorprendentemente, aún es más rápido cuando se observan datos alfabéticos puros:
También es importante tener en cuenta que los dos no producen la misma salida ordenada:
Por extraño que parezca, la
--buffer-size
opción no parecía hacer mucha (o ninguna) diferencia en mis pruebas. En conclusión, presumiblemente debido a los diferentes algoritmos mencionados en la respuesta de goldilock, pythonsort
parece ser más rápido en la mayoría de los casos, pero GNU numérico losort
supera en números no ordenados 1 .El OP probablemente ha encontrado la causa raíz, pero en aras de la exhaustividad, aquí hay una comparación final:
1 Alguien con más python-fu del que debería intentar probar los ajustes
list.sort()
para ver que se puede lograr la misma velocidad especificando el método de clasificación.fuente
sort
parece estar haciendo un poco de trabajo extra para las comparaciones en mayúsculas / minúsculas.stdin
entrada sin formato. La conversión de los números de (lines = map(int, list(stdin))
) y de vuelta (stdout.writelines(map(str,lines))
) hace que toda la clasificación ir más lento, hasta de 0.234s real para 0.720s en mi máquina.Ambas implementaciones están en C, por lo que hay igualdad de condiciones allí. Coreutils
sort
aparentemente usa el algoritmo mergesort . Mergesort realiza un número fijo de comparaciones que aumenta logarítmicamente al tamaño de entrada, es decir, O grande (n log n).La clasificación de Python utiliza una combinación híbrida / inserción híbrida única, timsort , que realizará un número variable de comparaciones con el mejor de los casos de O (n), presumiblemente, en una lista ya ordenada, pero generalmente es logarítmica (lógicamente, usted no puede ser mejor que logarítmico para el caso general al ordenar).
Dados dos tipos logarítmicos diferentes, uno podría tener una ventaja sobre el otro en algún conjunto de datos en particular. Un tipo de fusión tradicional no varía, por lo que realizará el mismo independientemente de los datos, pero, por ejemplo, la clasificación rápida (también logarítmica), que varía, funcionará mejor en algunos datos pero peor en otros.
Sin
sort
embargo, un factor de tres (o más de 3, ya que está en paralelo) es bastante, lo que me hace preguntarme si no hay alguna contingencia aquí, comosort
cambiar a disco (la-T
opción parece implicar que sí lo hace). Sin embargo, su bajo tiempo de sistema vs. usuario implica que este no es el problema.fuente