【发布时间】:2016-04-08 01:02:30
【问题描述】:
我用 C 语言编写了经典的素数筛选算法,它几乎可以立即在我的机器上生成所有小于 1,000,000 的素数(我没有做任何优化)。
在 Haskell 中,我使用 Ints 中的 Vector,并为每个质数生成一个更新列表,将倍数设置为零。这与我在 C 中使用嵌套 for 循环所做的基本相同:
import qualified Data.Vector.Unboxed as U
--| generate primes smaller than p
sievePrimes :: Int -> U.Vector Int
sievePrimes p = foldl f ns [0..p-1]
where
ns = U.fromList $ 0:[2..p]
f v i
| v U.! i == 0 = v
| otherwise = v U.// [((i + 1)*k - 1, 0) | k <- [2..p `div` (i + 1)]]
Haskell 版本的运行速度比 C 版本慢大约 1000 倍。我所做的所有优化都是使用vector 包。算法是一样的。
为什么运行这么慢? Vector 还不够高效吗?
我用 -O2 编译了 C 和 Haskell。
【问题讨论】:
-
关于 Haskell 中素数生成的问题有很多。你问之前搜索过吗?如果是这样,请花一些时间概述其他问题未涵盖的内容。如果不是......没有时间像现在这样!
-
无意冒犯,但链接的问题似乎基本相同,并且有一个出色的答案 - 连同来自 rampion 的链接文章,你应该很高兴 - 如果不是,请道歉
-
参见。 wiki.haskell.org/Prime_numbers#Accumulating_Array。更有效的是使用可变数组,比如wiki.haskell.org/Prime_numbers#Using_ST_Array。 Daniel Fischer 在 CodeReview 的某个地方提供了它的一个版本,使用循环而不是
forM和unsafeWrite,它的运行速度要快得多。否则,请参阅arithmoi包。 -
为你找到了它:Daniel's answer; my Ideone entry 带有仅赔率数组版本,始终比 comparable C++ version 慢 1.6 倍。和an immutable array version,它比 C++ 版本慢了大约 9.6 倍。总的来说,我们有 STUArray(unsafeWrite,loops) | STUArray(writeArray,forM) | UArray(分段) | UArray(连续累加数组)与 C++ 的速度比为
1.6x | 4.8x | 9.6x | 11x-13x。
标签: performance haskell vector primes sieve-of-eratosthenes