Haskell 如何在多核 machine/cluster 上处理并行计算

How Haskell handles parallel computing on a multicore machine/cluster

我正在考虑学习一种新语言,以便在我们拥有的计算机集群上进行高性能计算,在这些语言中,我正在考虑 Haskell。

我已经阅读了一些关于 Haskell 的内容,但仍然对在高性能和分布式计算中使用 Haskell 有疑问,这门语言是众所周知的,但我阅读了一些关于 [=47] 的辩论=] 由于懒惰不适合那些类型的系统,我可以在以下几行中总结我的问题:

  1. Haskell 使用绿色线程,这非常适合处理大量并发连接,但是当其中一个任务花费的时间超过平均时间并阻塞其余任务时会发生什么情况,整个线程会发生什么块(Node.js 样式),将下一个任务转发给另一个 processor/thread (Golang),使用缩减技术 (Erlang),在预定的滴答数后将任务踢出处理上下文,或者还有吗?

  2. 在分布式计算环境下,lazily-evaluated函数会发生什么情况,是否必须强制严格?

  3. 如果一个function/module需要严格求值,但是又依赖其他懒惰的functions/modules,我要不要修改其他functions/modules的代码让它们严格如好吧,否则编译器会为我处理这个问题,并强制该链中的所有内容严格或惰性。

  4. 当处理一个非常大的数据序列时,Haskell如何处理并行处理,是遵循某种隐式的map-reduce技术,还是我自己做的.

  5. 语言中是否有集群抽象,为我处理计算能力,自动将下一个任务转发给空闲处理器,无论它在哪里,无论是在同一台计算机还是另一台计算机上在同一个集群中。

  6. Haskell如何确保将工作公平分配给同一台计算机或可用集群上的所有可用内核。

  1. GHC 使用一个可用工作池(称为 sparks)和一个 work-stealing 系统:当线程用完工作时,它将在池中或它可以窃取的其他线程的工作队列中寻找工作。

  2. 没有像(比如说)Erlang 那样内置对分布式计算的支持。语义是您的实现定义的任何内容。您可以查看 Cloud Haskell 等现有实现作为示例。

  3. 都没有。 Haskell 将自动执行任何必要的工作以提供所需的值,仅此而已。

  4. Haskell(尤其是 GHC)不会自动并行化评估,因为没有已知的通用并行化策略严格来说比不并行化要好。有关详细信息,请参阅 Why is there no implicit parallelism in Haskell?

  5. 没有。见 (2).

  6. 对于同一台机器,它使用了上面描述的火花池和工作窃取系统。没有 "clustering".

  7. 的概念

有关 Haskell 中并行和并发编程的概述,请参阅 GHC 运行时系统的主要作者 Simon Marlow 的 free book of the same name

多线程

就SMP parallelism而言,Haskell非常有效。它的 not quite automatic, but the parallel library 使得几乎任何事情的并行化都变得非常容易。因为火花太便宜了,你可以很粗心,只要求 lots 的并行度;然后运行时将知道要做什么。
与大多数其他语言不同,如果你有高度分支的数据结构、棘手的动态算法等,这不是一个大问题——多亏了纯函数范式,并行 Haskell 永远不需要担心锁 当访问的数据被共享时。

我认为最大的警告是内存:GHC 的垃圾收集器不是并发的,函数式风格更适合分配。
除此之外,可以编写 看起来 并行的程序,但实际上根本不做任何工作,只是立即启动 return 因为懒惰。一些测试和经验仍然是必要的。但是惰性和并行性并不是不相容的;至少如果您确保其中有足够大的“块”严格性,则不会。强制执行严格的事情在很大程度上是微不足道的。

通常可以在 Haskell 与并行化 数据结构 的库;其中最著名的是 repa.

分布式计算

Cloud Haskell 上已经有很多工作,基本上是库形式的 Erlang。这种任务不那么简单:任何显式消息发送的想法都有点违背 Haskell 的风格,如果语言如此专注于其强大的静态类型,那么工作流的许多方面都会变得更加繁琐(这在 Haskell 中通常是一个巨大的好处,它不仅提高了安全性和性能,而且还使编写更容易。

我认为以分布式并发方式使用 Haskell 已经不远了,但我们还不能说它在那个角色上已经成熟了。对于分布式并发任务,Erlang 本身无疑是最佳选择。

集群

老实说,Haskell 在这里对您帮助不大。集群原则上当然是分布式设置的特例,因此您可以使用云Haskell;但在实践中,需求却大不相同。今天的 HPC 世界(可能在未来相当长的一段时间内)取决于 MPI,尽管 there is a bit of existing work on MPI bindings,我还没有发现它们可用,至少不是 就像那样 .

MPI 绝对也很反对 Haskell 的风格,它是面向 FORTRAN 的数组中心主义,处理类型的怪异方式等等。但是,除非您对 Haskell 的酷炫功能发疯(尽管通常 所以 很诱人!),否则您没有理由不能在其中编写典型的数字运算代码Haskell。唯一的问题又是 support/maturity,但这是一个相当大的问题;所以对于集群计算,我建议使用 C++,Python 或 Julia。

一个有趣的替代方法是从 Haskell 生成 MPI 并行化的 C 或 C++ 代码。 Paraiso 是一个很好的项目。

白日梦

我经常思考如何才能使分布式计算在惯用语中变得可行 Haskell。 原则上我相信懒惰可能会有很大的帮助。我设想的模型是让所有机器 独立地 计算同一个程序,但要利用 Haskell 评估通常没有预定顺序这一事实。每台机器上的顺序将是随机。此外,运行时将跟踪某些计算分支需要多长时间才能完成,以及结果有多大。如果一个结果被认为既昂贵又紧凑,足以保证它,它就会被广播到其他节点,连同一些合适的哈希值,使它们能够简化计算。

这样的系统永远不会像手动优化的 MPI 应用程序那样高效,但它至少可以在许多情况下提供相同的渐近线。而且它可以轻松处理更复杂的算法。

不过,这完全只是我对不久的将来的模糊希望。


你说 并发(与其说是计算,不如说是交互), 但你的问题似乎本质上是关于纯计算的?