7

F# で Task Parallel Library (TPL) を使用して、多くの (>1000) 実行時間の長いタスクを実行したいと考えています。これが私の現在のコードです:

Parallel.For(1, numberOfSets, fun j ->
    //Long running task here
    )

これを開始すると、.NET がすべてのタスクを一度に開始し、それらの間を常にバウンスしているように見えます。次のタスクに移る前に、タスクが完了するまでタスクにとどまるとよいでしょう。これにより、コンテキストの切り替えが最小限に抑えられます。

スケジューラにヒントを提供する方法はありますか? ヒントを提供できることはわかっていますが、明確な例が見つからないか、スケジューラがすでにこれについてスマートであり、コンテキストの切り替えが多すぎるというのは私の認識です。助けてくれてありがとう!

4

3 に答える 3

8

同様の問題がありました。F# ではなく C# を使用していますが、ライブラリは同じです。解決策は、並列度を制限することでした。

ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 16;
Parallel.For(0, n, parallelOptions, i => {
   . . . 
});

16 は私たちのタスクではうまくいきました - あなたのケースではどの値がより良いかを実験する必要があります.

于 2012-11-24T18:56:15.583 に答える
5

私の経験から、多数のタスクの場合は、MaxDegreeOfParallelism線形ににバインドする方が適切Environment.ProcessorCountです。

以下は、F# 構文での @Mimo のものと同様のコード フラグメントです。

let options = ParallelOptions()
options.MaxDegreeOfParallelism <- Environment.ProcessorCount * 2

Parallel.For(0, n, options, 
             (fun i -> (* Long running task here *))) |> ignore

F# で並列プログラミングを行っているので、優れた本「Parallel Programming with Microsoft .NET」、特に「Parallel Loops」の章を参照してください。@Tomas はそのサンプルを F# に翻訳しており、こちらから入手できます。

于 2012-11-25T01:48:50.767 に答える
1

参照ソースを見ると、次のコードがワーカーの数を決定しているようです。

// initialize ranges with passed in loop arguments and expected number of workers 
int numExpectedWorkers = (parallelOptions.EffectiveMaxConcurrencyLevel == -1) ?
    Environment.ProcessorCount : 
    parallelOptions.EffectiveMaxConcurrencyLevel; 

私が知る限り、デフォルトのタスク スケジューラとデフォルトの ParallelOptions を使用すると、これは に評価されるため、プロセッサ カウントを自分Environment.ProcessorCountで指定することで異なる動作が得られるのは奇妙です。MaxDegreeOfParallelism実際に違いがあることを確認するためにデバッグすることをお勧めします (Thread.ManagedThreadId長時間実行されるタスク内に出力できます)。

于 2012-11-25T10:38:32.110 に答える