実行制限付きの並列計算

個人的にご質問をいただいたので、簡単なサンプルを書いてみました。
「たくさんの処理を並列に実行したいのだけど、同時に走るスレッド数は制限したい」というプログラムです。



let worker (id: int) = async {
System.Console.WriteLine("Worker:{0}", id) // 並列環境ではprintfnは使用しない
do! Async.Sleep(1500)
}

[<EntryPoint>]
let main argv =
List.init 15 worker // 15個の処理をしたい
|> List.chunkBySize 3 // 3つずつ並列化したい
|> List.iter
(Async.Parallel >> Async.Ignore >> Async.RunSynchronously)

printfn "completed"
0


実行すると、1.5秒ごとに3行ずつ表示されます。

Worker:1
Worker:0
Worker:2
Worker:3
Worker:5
Worker:4
Worker:6
Worker:7
Worker:8
Worker:9
Worker:11
Worker:10
Worker:12
Worker:14
Worker:13
completed


F#ではasync式によって構築された計算はオブジェクトのように扱うことができます。
サンプルでは、計算15個のリストを生成し、それを3つずつに分割して並列実行しています。
3つの式がほぼ同時に実行されますが、RunSynchronouslyメソッドで結果を待機しているので、その3つの計算が完了してから残りの式が実行されることになります。(以降はその繰り返し)