gpt4 book ai didi

haskell - 为什么 Haskell 列表推导式不并行执行?

转载 作者:行者123 更新时间:2023-12-02 05:41:38 25 4
gpt4 key购买 nike

我正在做 Project Euler 问题 21 作为家庭作业,我有这个列表理解:

amicableNumberSums = [ x+y | x<-[1..10000], y <-[1..10000], (amicable x y)]

这需要很长时间才能执行(可以理解,因为它测试了 10000^2 对数字),并且查看我的 CPU 使用情况,它显示只使用了 1 个核心。

由于列表理解没有副作用,因此同时测试多对数字没有危险。有没有办法让 Haskell 自动执行此操作,或者如果没有,如何修改我的代码来执行此操作?

(编辑)运行打印时出错(amicableNumberSums using parList):

Couldn't match type `a0 -> Eval a0' with `[Int]'
Expected type: Strategy [Int]
Actual type: Strategy a0 -> Strategy [a0]
In the second argument of `using', namely `parList'
In the first argument of `print', namely
`(amicableNumberSums `using` parList)'
In the expression: print (amicableNumberSums `using` parList)

(编辑)两种建议方法的性能:

Ørjan Johansen's method: 218.79s elapsed parallel (4 cores + 4 hyperthreading)
279.37s elapsed sequential (single core)
bheklilr's method: 247.82s elapsed parallel (4 cores + 4 hyperthreading)
274.10s elapsed sequential (single core)
Original method: 278.69s elapsed

这并没有我希望的那么大的速度提升,但我现在有了问题的正确答案,在我学习更多 Haskell 之前,这已经足够了。

最佳答案

这是一个简单的例子:

simple = 1 : 1 : [a + b | a <- simple, b <- simple]

你会如何并行化它?您如何将其推广到任何列表理解来决定它是否可以并行化?对于无限列表的任何其他列表理解怎么样,为每个元素引发一个新线程将意味着引发无限线程。如果由于线程开销太大并减慢计算速度,顺序计算列表实际上要快得多怎么办?如果只需要列表的前 10 个元素怎么办?当需要一小部分时,贪婪地计算整个列表并不是很好。

相反,GHC 选择让程序员有权决定何时以及如何并行化列表计算。您可以使用 Control.Parallel.Strategies 模块选择如何完成操作,而不是隐式为您执行操作:

print $ amicableNumberSums `using` parList rdeepseq

或者并行计算列表的 block :

print $ amicableNumberSums `using` parListChunk 64 rdeepseq

请记住,您必须使用 seq 和 co。在正确的时间将您的数据导入 NF。

Control.Parallel.Strategies 公开的 API 使您能够定义并行计算纯数据结构的不同方法,完全独立于数据结构本身甚至其他算法。这与大多数其他编程语言形成鲜明对比,这些语言迫使您将并行性与其他算法甚至结构的构建方式紧密结合起来。我强烈推荐阅读 Simon Marlow 的 Parallel and Concurrent Haskell (它是在线免费的!),它在解释它的工作原理和使用方法方面比我做得更好。

关于haskell - 为什么 Haskell 列表推导式不并行执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25732248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com