6

我有一个闭源非线程安全 C++ 共享库,它提供一个函数 f :: ByteString -> ByteString。此函数的运行时间可能在一秒到几个小时之间。

我正在寻找一种将计算分配到多个核心/服务器 (SIMD) 的方法。

简而言之,我正在寻找一个提供功能的框架

    g :: Strategy b -> (a -> b) -> a -> b

将只能按顺序调用的函数提升为行为类似于 Haskell 中任何其他纯函数的函数。

例如,我希望能够编写:

    parMap rwhnf f args -- will not work

由于 f 通过 FFI 在非线程安全库中调用 C 函数,因此这将不起作用。因此,我可以将函数 f 替换为函数 g,该函数保存一个作业队列并将任务分派给 N 个单独的进程。这些进程可以在本地或分布式运行:

    parMap rwhnf g args -- should works

我已经研究过的潜在框架是

  1. MPI : 客户端 (Haskell) <-- MPI --> Broker (C++) <-- MPI --> Worker (C++) <--> Lib (C++)

  2. ZeroMQ : Client (Haskell) <-- ZeroMQ --> Broker (C++) <-- ZeroMQ --> Worker (C++) <--> Lib (C++)

  3. Cloud Haskell : 客户端 (Haskell) <-- CloudHaskell --> Worker (Haskell) <-- FFI --> Lib (C++)

  4. 齿轮人

  5. Erlang : Client (Haskell) <-- Erlang --> Broker (Erlang) <-- Erlang C Node --> Worker (C++)

每种方法都有优点和缺点。

  1. MPI 会产生很多安全问题,是一个相当重量级的解决方案。

  2. ZeroMQ 是一个不错的解决方案,但需要我自己编写代理/负载均衡器等(尤其是获得正确的可靠性并非易事)。

  3. CloudHaskell 看起来不是很成熟。

  4. Gearman 不在 Windows 上运行,也没有 Haskell 绑定。我知道 java-gearman-service,但它比 C 守护程序成熟得多,并且还有一些其他问题(例如,没有文档,如果一段时间内没有传入的任务流则关闭,等等)。

  5. 与 1 类似,需要使用第三种语言。

谢谢!

4

1 回答 1

1

由于您使用的库不是线程安全的,因此您需要一个基于使用进程作为并行抽象的解决方案。您希望使用 Par monad 看到的示例使用基于 spark 或任务的并行模型,其中许多 spark 可以存在于同一个线程中。显然这不是你要找的。

不要害怕!

Haskell 中只有少数范例以这种方式工作,您在文章 Cloud Haskell 中提到了其中之一。虽然 Cloud Haskell 并不“成熟”,但它可以解决您的问题,但对于您的需求,它可能有点重量级。如果您真的只需要使用进程级并行抽象来利用许多本地内核,那么请查看 Eden 库:

http://www.mathematik.uni-marburg.de/~eden/

使用 Eden,您可以完全表达自己的追求。这是一个非常简单的示例,类似于基于 Par Monad 的版本:

f $# args

或者在有很多争论的情况下,您可能只是拉出 ye olde map:

map f $# args

有关 $# 语法的更多信息以及有关 Eden 的教程,请参阅:

http://www.mathematik.uni-marburg.de/~eden/paper/edenCEFP.pdf

YMMV 作为 Haskell 中大多数更成熟的并行范例,假设您具有一定程度的线程安全性,或者使用可以以纯粹的方式进行并行工作。

祝你好运,黑客快乐!

于 2012-07-12T19:15:54.353 回答