在 Haskell/GHC 中驯服并行性
Taming parallelism in Haskell/GHC
一个 Haskell 新手提出的关于使并行有效工作的问题。
Advent of Code Day 14 挑战涉及创建整数序列的 MD5 散列,寻找满足特定属性的散列的前 n 个整数。我基本上是通过创建哈希然后过滤它们来做到这一点的。
我认为尝试使用多个内核来生成哈希值的并行性是一件好事。
哈希创建的非并行版本如下所示:
md5sequenceS :: [String]
md5sequenceS = [makeMd5 i | i <- [0..]]
where makeMd5 i = stretch $ getHash (salt ++ show i)
stretch h0 = foldr (\_ h -> getHash h) h0 [1..2016]
...它工作正常,虽然速度很慢,大约四分钟内给出答案。
并行版本是这样的:
md5sequenceS :: [String]
md5sequenceS = parMap rdeepseq (makeMd5) [0..]
where makeMd5 i = stretch $ getHash (salt ++ show i)
stretch h0 = foldr (\_ h -> getHash h) h0 [1..2016]
...除了 parMap rdeepseq
位之外与之前相同。这不能很好地工作:它消耗了我机器上的所有可用内存,并且在挂起 30 分钟后仍然无法产生答案。但是,它确实充分利用了所有处理器。
我应该怎么做才能驯服这种失控的并行性?
(问题规范没有给出我需要生成多少散列的任何线索,但事实证明我需要散列大约 30,000 个整数。)
编辑以包含已接受的答案
parBuffer
策略可以用作
md5sequenceS = withStrategy (parBuffer 100 rdeepseq) $ map (makeMd5) [0..]
where makeMd5 i = stretch $ getHash (salt ++ show i)
stretch h0 = foldr (\_ h -> getHash h) h0 [1..2016]
与单线程版本相比,性能不是很好,但这是一个不同的问题...
parMap
将强制评估所有列表,在您的情况下是无限的。
除了使用 parMap
,您可以考虑使用其他策略,例如能够处理无限列表的 parBuffer
。
一个 Haskell 新手提出的关于使并行有效工作的问题。
Advent of Code Day 14 挑战涉及创建整数序列的 MD5 散列,寻找满足特定属性的散列的前 n 个整数。我基本上是通过创建哈希然后过滤它们来做到这一点的。
我认为尝试使用多个内核来生成哈希值的并行性是一件好事。
哈希创建的非并行版本如下所示:
md5sequenceS :: [String]
md5sequenceS = [makeMd5 i | i <- [0..]]
where makeMd5 i = stretch $ getHash (salt ++ show i)
stretch h0 = foldr (\_ h -> getHash h) h0 [1..2016]
...它工作正常,虽然速度很慢,大约四分钟内给出答案。
并行版本是这样的:
md5sequenceS :: [String]
md5sequenceS = parMap rdeepseq (makeMd5) [0..]
where makeMd5 i = stretch $ getHash (salt ++ show i)
stretch h0 = foldr (\_ h -> getHash h) h0 [1..2016]
...除了 parMap rdeepseq
位之外与之前相同。这不能很好地工作:它消耗了我机器上的所有可用内存,并且在挂起 30 分钟后仍然无法产生答案。但是,它确实充分利用了所有处理器。
我应该怎么做才能驯服这种失控的并行性?
(问题规范没有给出我需要生成多少散列的任何线索,但事实证明我需要散列大约 30,000 个整数。)
编辑以包含已接受的答案
parBuffer
策略可以用作
md5sequenceS = withStrategy (parBuffer 100 rdeepseq) $ map (makeMd5) [0..]
where makeMd5 i = stretch $ getHash (salt ++ show i)
stretch h0 = foldr (\_ h -> getHash h) h0 [1..2016]
与单线程版本相比,性能不是很好,但这是一个不同的问题...
parMap
将强制评估所有列表,在您的情况下是无限的。
除了使用 parMap
,您可以考虑使用其他策略,例如能够处理无限列表的 parBuffer
。