如何限制为F#中的异步Seq.map操作创建的线程数?

Ale*_*der 7 f# multithreading

目前的设置是这样的

array
|> Seq.map (fun item -> async { return f item})
|> Async.Parallel
|> Async.RunSynchronously
Run Code Online (Sandbox Code Playgroud)

问题是,这往往会创建太多线程并定期崩溃应用程序.

在这种情况下如何限制线程数(比如说,Environment.ProcessorCount)?

HTC*_*HTC 5

自 2018 年拉取请求以来,F# Core 中通过F# 文档的第二次重载提供了一个内置选项Async.Parallel

array
|> Seq.map (fun item -> async { return f item})
|> fun computations -> Async.Parallel(computations, maxDegreeOfParallelism = 20)
|> Async.RunSynchronously
Run Code Online (Sandbox Code Playgroud)


Tom*_*cek 3

如果您想要并行化以数组(或任何序列)作为输入的 CPU 密集型计算,那么使用F# PowerPackPSeq中的模块(尽管仅在 .NET 4.0 上可用)可能是更好的主意。它提供了许多标准函数的并行版本。有关更多信息,您还可以查看使用 .NET 进行并行编程示例的F# 翻译Array.xyz

解决您的问题的代码比使用工作流程要简单一些:

array |> PSeq.map f
      |> PSeq.toArray 
Run Code Online (Sandbox Code Playgroud)

这两个选项之间的一些区别是:

  • PSeq是使用 .NET 4.0 中的任务并行库 (TPL) 创建的,该库针对处理大量 CPU 密集型任务进行了优化。
  • 异步在 F# 库中实现,支持异步(非阻塞)操作,例如并发运行操作中的 I/O。

总之,如果您需要异步操作(例如 I/O),那么这Async是最好的选择。如果您有大量 CPU 密集型任务,那么PSeq可能是更好的选择(在 .NET 4.0 上)