繁体   English   中英

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

[英]How to limit the number of threads created for an asynchronous Seq.map operation in F#?

当前的设置是这样的

array
|> Seq.map (fun item -> async { return f item})
|> Async.Parallel
|> Async.RunSynchronously

如果要并行化将数组(或任何序列)作为输入的CPU密集型计算,则最好使用F#PowerPack中的 PSeq模块(尽管它仅在.NET 4.0中可用)。 它提供了许多标准Array.xyz函数的并行版本。 有关更多信息,您还可以查看带有.NET示例的并行编程的 F#转换

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

array |> PSeq.map f
      |> PSeq.toArray 

两种选择之间的一些区别是:

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

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

这是一个根据Brian的建议,如何使用信号量来执行此操作的示例:

open System

let throttle n fs =
    seq { let n = new Threading.Semaphore(n, n)
          for f in fs ->
              async { let! ok = Async.AwaitWaitHandle(n)
                      let! result = Async.Catch f
                      n.Release() |> ignore
                      return match result with
                             | Choice1Of2 rslt -> rslt
                             | Choice2Of2 exn  -> raise exn
                    }
        }

let f i = async { printfn "start %d" i
                  do! Async.Sleep(2000)
                }
let fs = Seq.init 10 f

fs |> throttle 2 |> Async.Parallel |> Async.RunSynchronously |> ignore

您可能会做几件事。

首先,由于这使用了ThreadPool ,因此可以使用ThreadPool.SetMaxThreads

其次,您可以按照以下方式引入自己的节流阀:

let throttle = makeThrottle(8)
array 
|> Seq.map (fun item -> async { do! throttle.Wait()
                                return f item}) 
|> Async.Parallel 
|> Async.RunSynchronously 

makeThrottle()不会太难编写,但是会产生一些同步开销。 如果您试图并行化太多事情以致内存不足,那么节流开销很可能不是问题。 (如果您需要这种代码的样本,请告诉我。)

最后,如果这确实使事情崩溃了,它闻起来好像是您做错了什么。 ThreadPool通常(但并非总是如此)在管理自身方面做得很好。 但是,在各种情况下,设计自己的节流阀对您的应用而言仍然很有价值。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM