作为编程挑战的一部分,我需要从stdin读取一系列由空格分隔的整数(在单行上),并将这些整数的总和打印到stdout。所涉及的序列可以包含多达10,000,000个整数。
我有两个解决方案:一个用Haskell编写(foo.hs),另一个等效的解决方案用Python 2编写(foo.py)。不幸的是,(已编译的)Haskell程序始终比Python程序慢,并且我无法解释这两个程序之间性能差异的原因;请参阅下面的基准测试部分。如果有什么区别,我原本希望Haskell能够占优势...
我做错了什么?如何解释这种差异?有没有简单的方法加速我的Haskell代码?
(供参考,我使用的是带有8Gb RAM、GHC 7.8.4和Python 2.7.9的中2010年Macbook Pro。)
我有两个解决方案:一个用Haskell编写(foo.hs),另一个等效的解决方案用Python 2编写(foo.py)。不幸的是,(已编译的)Haskell程序始终比Python程序慢,并且我无法解释这两个程序之间性能差异的原因;请参阅下面的基准测试部分。如果有什么区别,我原本希望Haskell能够占优势...
我做错了什么?如何解释这种差异?有没有简单的方法加速我的Haskell代码?
(供参考,我使用的是带有8Gb RAM、GHC 7.8.4和Python 2.7.9的中2010年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
read :: String -> Integer
至少在最近的一个补丁之前是二次方的。不确定是否对于Int
使用了相同类型的算法... - Bakuriuread
不是正确的工具。read
旨在解析有效的 Haskell 表达式,因此类似"((( 0x8485) ))"
的内容会以相当高的额外成本成功解析。请使用适当的工具来解析整数。 - Thomas M. DuBuisson