11

我之前问过一个相关的问题,为什么 OCaml 的线程被认为是“不够”?

不管 ocaml 的线程有多“糟糕”,我注意到一些库说他们可以做真正的线程。

例如,Lwt

Lwt 提供了一个新的选择。它提供了非常轻量级的协作线程;“启动”一个线程是一个非常快的操作,它不需要一个新的堆栈、一个新的进程或其他任何东西。此外,上下文切换非常快。事实上,这很容易,我们将为每个系统调用启动一个线程。组合协作线程将使我们能够编写高度异步的程序。

如果我是对Jane Street的,那么aync_core也提供了类似的东西。


但我很困惑。做Lwtaync_core提供线程之类的Java threading

如果我使用它们,我可以使用多个 cpu 吗?

以什么方式,我可以在 OCaml 中获得“真正的线程”(就像在 Java 中一样)?


编辑

我仍然很困惑。

让我添加一个场景:

我有一个服务器 ( 16 cpu cores) 和一个服务器应用程序。

服务器应用程序的作用是:

  • 它监听请求
  • 对于每个请求,它都会启动一个计算任务(假设需要 2 分钟才能完成)
  • 当每个任务完成时,任务要么将结果返回给主任务,要么直接将结果发送回客户端

在 Java 中,这很容易。我创建一个线程池,然后对于每个请求,我在该池中创建一个线程。该线程将运行计算任务。这在 Java 中是成熟的,它可以利用 16 个 cpu 内核。我对吗?

所以我的问题是:我可以在 OCaml 中做同样的事情吗?

4

2 回答 2

16

您引用的并行化服务器示例是使用简单的多处理模型很好地解决的那些令人尴尬的并行问题之一,使用fork. 几十年来,这在 OCaml 中一直是可行的,是的,如果需要,您将使用机器的所有内核实现几乎线性的加速。

要使用标准库的简单原语来做到这一点,请参阅在线书籍“OCaml 中的 Unix 系统编程”(2003 年首次发布)的这一章和/或在线书籍“使用 OCaml 开发应用程序”的这一章(首先2000 年发布)。

您可能还想使用更高级别的库,例如 rafix 提到的 Gerd Stolpmann 的OCamlnet库,它提供了很多东西,从通常的客户端/服务器设计的直接助手到低级多进程通信库;请参阅文档

Parmap也很有趣,但可能用于稍微不同的用例(更多的是您同时拥有大量可用的数据,您希望使用相同的函数并行处理):插入式替换of Array.mapor List.map(or fold) 并行化计算。

于 2013-05-15T13:15:55.280 回答
11

您会发现最接近真实(抢占式)线程的是内置线程库。这意味着我的意思是你的编程模型将是相同的,但有两个重要的区别:

  • OCaml 的本机线程不像 Java 那样轻量级。
  • 一次只能执行一个线程,因此您无法利用多个进程。

这使得 OCaml 的线程对于并发性或并行性来说是一个非常糟糕的解决方案,因此通常人们避免使用它们。但它们仍然有它们的用途。

Lwt 和 Async 非常相似,并为您提供了不同的线程风格 - 一种协作风格。协作线程与抢占式线程的不同之处在于,线程之间的上下文切换在代码中是明确的,并且阻塞调用从类型签名中总是显而易见的。提供的协作线程非常便宜,因此非常适合并发,但同样不会帮助您处理并行性(由于 OCaml 运行时的限制)。

有关协作线程的良好介绍,请参阅此:http: //janestreet.github.io/guide-async.html

编辑:对于您的特定场景,我将使用 Parmap,如果任务像您的示例中那样计算密集,那么从 parmap 启动进程的开销应该可以忽略不计。

于 2013-05-15T10:52:05.297 回答