【发布时间】:2015-05-25 01:02:47
【问题描述】:
作为编程挑战的一部分,我需要从标准输入读取一系列以空格分隔的整数(在一行),并将这些整数的总和打印到标准输出。有问题的序列可以包含多达 10,000,000 个整数。
我有两种解决方案:一种是用 Haskell (foo.hs) 编写的,另一种是等效的,用 Python 2 (foo.py) 编写的。不幸的是,(编译的)Haskell 程序一直比 Python 程序慢,我无法解释这两个程序之间的性能差异。请参阅下面的基准部分。如果有的话,我本以为 Haskell 会占上风……
我做错了什么?我该如何解释这种差异?有没有一种简单的方法可以加速我的 Haskell 代码?
(有关信息,我使用的是 2010 年中期配备 8Gb RAM、GHC 7.8.4 和 Python 2.7.9 的 Macbook Pro。)
foo.hs
main = print . sum =<< getIntList
getIntList :: IO [Int]
getIntList = fmap (map read . words) getLine
(用ghc -O2 foo.hs编译)
foo.py
ns = map(int, raw_input().split())
print sum(ns)
基准测试
在下文中,test.txt 由一行 1000 万个以空格分隔的整数组成。
# Haskell
$ time ./foo < test.txt
1679257
real 0m36.704s
user 0m35.932s
sys 0m0.632s
# Python
$ time python foo.py < test.txt
1679257
real 0m7.916s
user 0m7.756s
sys 0m0.151s
【问题讨论】:
-
您的测试文件几乎全为零。这真的是一个很好的测试吗?
-
@dfeuer 我没有生成那个文件。它恰好是比赛期间给出的测试用例之一。这可能很糟糕或无趣,但我对此没有发言权。
-
我知道
read :: String -> Integer至少在最近的补丁之前是二次的。不确定Int是否使用了同一种算法... -
注意
read当您的格式只是 ints 时,它是适合该工作的错误工具。read旨在解析有效的 haskell 表达式,所以像"((( 0x8485) ))"这样的东西可以很好地解析,但需要付出相当多的额外费用。
标签: python performance haskell io