【问题标题】:Haskell Vector performance woesHaskell Vector 性能问题
【发布时间】: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 的某个地方提供了它的一个版本,使用循环而不是 forMunsafeWrite,它的运行速度要快得多。否则,请参阅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


【解决方案1】:

您需要将您的 foldl 呼叫替换为 foldl f ns [0 .. floor . sqrt . fromIntegral $ p]。这从根本上提高了时间复杂度,正如 haskell-wiki 中所解释的那样,因为 the cost of U.// is O(m+n) 而不是 O(n),因为它在具有破坏性更新的语言中,如 C;这就是为什么不尽快停止不会恶化那里的时间复杂度的原因。

但在 Haskell 中,尽快停止处理不可变数据至关重要,因为更新操作的时间复杂度更差,对于列表和 Vectors 也是如此。

在分析一段代码的性能时,始终通过在几个问题大小点测量其速度并计算 logBase (n2/n1) (t2/t1) 来分析其empirical orders of growth

更新的代码,在我的计算机上用 GHCi 解释,在 3.53 秒内生成低于 N = 1,000,000n = 78,498 素数,运行在 ~N1.1 或者 ~n1.2,很体面。

您的代码以 N = 40,000/20,000 测量,运行时间为 ~N1.7~n 1.9,非常慢;如果复杂度保持不变,预计到 1,000,000 的运行时间为 7 分钟。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多