【问题标题】:Infinite list parallel filter in HaskellHaskell中的无限列表并行过滤器
【发布时间】:2016-10-18 09:14:18
【问题描述】:

我想在 Haskell 的无限列表中找到第一个匹配的元素。

此代码正在运行:

findPassword passwordHash = (head . filter (checkPassword passwordHash)) allStrings

checkPassword 真的很长(因为它是 SHA1 哈希)

checkPassword hash string = (sha1 string) == hash

allStrings 只是所有可能字符串的列表:

allStrings = [ c : s | s <- "" : allStrings, c <- ['a'..'z'] ++ ['0'..'9'] ]

我希望这段代码并行运行,但如果我用 parFilter 替换过滤器:

import qualified Control.Parallel.Strategies as S
parFilter p = S.withStrategy (S.evalBuffer 1000 S.rseq) . filter p

它不起作用……你有什么想法吗?这段代码也使用了大量内存,但这是另一个问题。 完整的脚本在这里https://github.com/ThibaudDauce/habreaker

【问题讨论】:

  • 你怎么知道它不起作用?
  • 它永远运行并吃掉我所有的内存和处理器

标签: haskell parallel-processing infinite


【解决方案1】:

我很确定您想使用 parBuffer 而不是 evalBuffer

请参阅此 SO 答案以获得很好的解释:

How to choose between parList and parBuffer?

这是一些演示代码:

import qualified Data.Map.Strict as M
import Control.Parallel.Strategies
import System.Environment
import Debug.Trace

fib 0 = 0
fib 1 = 1
fib n = fib (n-2) + fib (n-1)

fib' n | trace "calling fib" False = undefined
fib' n = fib n

theList = cycle [30,31,32]

firstN :: Int -> [Int]
firstN n = take n $ filter even $ map fib' theList

firstNpar :: Int -> Int -> [Int]
firstNpar n k = take n $ filter even $ runEval $ parBuffer k rseq $ map fib' theList

main = do
  (argn : argk : _) <- getArgs
  let n = read argn
  case argk of
    "" -> print $ firstN n
    _  -> let k = read argk in
          print $ firstNpar n k

示例运行:

prog 20 2 +RTS -N2         -- I only have two cores
prog 20 ''                 -- run single threaded

【讨论】:

  • 谢谢,它可以工作 (github.com/ThibaudDauce/habreaker),但速度并不快…… :-( 而且我没有看到我所有的处理器都在工作……
  • 尝试使用rdeepseq 而不是rseqrseq 适用于我的示例,因为 fib 的结果只是数字,但您正在计算一对,因此评估 WHNF 不会计算哈希。
猜你喜欢
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
  • 2017-04-17
  • 2017-09-28
相关资源
最近更新 更多