Je dispose d'un script simple écrit à la fois en Python et en Haskell. Il lit un fichier contenant 1 000 000 d'entiers séparés par des sauts de ligne, analyse ce fichier pour en faire une liste d'entiers, les trie rapidement, puis les écrit dans un autre fichier trié. Ce fichier a le même format que le non trié. Simple.
Voici Haskell:
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where
lesser = filter (< p) xs
greater = filter (>= p) xs
main = do
file <- readFile "data"
let un = lines file
let f = map (\x -> read x::Int ) un
let done = quicksort f
writeFile "sorted" (unlines (map show done))
Et voici Python:
def qs(ar):
if len(ar) == 0:
return ar
p = ar[0]
return qs([i for i in ar if i < p]) + [p] + qs([i for i in ar if i > p])
def read_file(fn):
f = open(fn)
data = f.read()
f.close()
return data
def write_file(fn, data):
f = open('sorted', 'w')
f.write(data)
f.close()
def main():
data = read_file('data')
lines = data.split('\n')
lines = [int(l) for l in lines]
done = qs(lines)
done = [str(l) for l in done]
write_file('sorted', "\n".join(done))
if __name__ == '__main__':
main()
Très simple. Maintenant je compile le code Haskell avec
$ ghc -O2 --make quick.hs
Et je les mesure avec le temps :
$ time ./quick
$ time python qs.py
Résultats:
Haskell:
real 0m10.820s
user 0m10.656s
sys 0m0.154s
Python:
real 0m9.888s
user 0m9.669s
sys 0m0.203s
Comment Python peut-il être plus rapide que le code natif Haskell?
Merci
ÉDITER:
- Version Python: 2.7.1
- Version GHC: 7.0.4
- Mac OSX, 10.7.3
- Intel Core i5 2.4GHz
Liste générée par
from random import shuffle
a = [str(a) for a in xrange(0, 1000*1000)]
shuffle(a)
s = "\n".join(a)
f = open('data', 'w')
f.write(s)
f.close()
Donc tous les numéros sont uniques.
11 votes
Bug dans l'implémentation python? Vous construisez les sous-listes avec
i > p
eti < p
. Que se passe-t-il lorsquei = p
?1 votes
Eh bien, je suppose que la plupart du temps d'exécution de Python est passé dans le code C qui concatène les listes Python (tableaux dynamiques, au cas où quelqu'un ne le saurait pas).
cProfile
devrait vous dire si c'est vrai.0 votes
Avez-vous confirmé que la sortie des programmes est exactement la même?
0 votes
Le fichier d'entrée a-t-il été mis en cache avant que vous n'exécutiez le programme Haskell? Il semble que oui avant d'exécuter le programme Python.
5 votes
Comment 9.9 peut-il être plus rapide que 10.8? Une simple erreur de lecture en HD pourrait causer une différence dix fois supérieure.
1 votes
Quelles versions de GHC et de Python utilisez-vous ? Je reçois une exception lorsque j'essaie d'exécuter votre code Python (Python 2.6.5 --- Je ne suis pas un Pythonista).
16 votes
Notez que vous chronométrez principalement les E/S et la conversion entre les entiers et les chaînes. Remplacer l'appel à
quicksort
parid
ne fait diminuer le temps d'exécution que d'environ 30% sur ma machine.0 votes
@dave: Essayez d'ajouter
from __future__ import generators
en haut du fichier.1 votes
@NiklasB. Je continue à obtenir l'erreur
ValueError: valeur non valide pour int() avec la base 10 : ''
pour la deuxième lignelines =
dansmain
.