【发布时间】:2012-04-27 20:51:20
【问题描述】:
我有一个用 Python 和 Haskell 编写的简单脚本。它读取包含 1,000,000 个换行符分隔的整数的文件,将该文件解析为整数列表,对其进行快速排序,然后将其写入已排序的不同文件。该文件与未排序的文件具有相同的格式。很简单。
这是 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))
这里是 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()
非常简单。现在我用
编译Haskell代码$ ghc -O2 --make quick.hs
我将这两个时间用:
$ time ./quick
$ time python qs.py
结果:
哈斯克尔:
real 0m10.820s
user 0m10.656s
sys 0m0.154s
Python:
real 0m9.888s
user 0m9.669s
sys 0m0.203s
Python 怎么可能比原生代码 Haskell 更快?
谢谢
编辑:
- Python 版本:2.7.1
- GHC 版本:7.0.4
- Mac OSX,10.7.3
- 2.4GHz 英特尔酷睿 i5
列表生成者
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()
所以所有数字都是唯一的。
【问题讨论】:
-
python 实现中的错误?您正在使用
i > p和i < p构建子列表。i = p的时候呢? -
好吧,我猜大部分 Python 运行时间都花在了连接 Python 列表(动态数组,以防有人不知道)的 C 代码中。
cProfile应该会告诉你这是不是真的。 -
9.9 比 10.8 快多少?一个简单的高清读取错误可能会导致十倍的差异。
-
您使用的是哪个版本的 GHC 和 Python?当我尝试运行您的 Python 代码时出现异常(Python 2.6.5 --- 我不是 Pythonista)。
-
请注意,您主要是在计时 I/O 以及在整数和字符串之间进行转换。用
id替换对quicksort的调用只会将我机器上的运行时间减少约30%。