1

1 コアのマシンを使用しており、async と await を使用してコードのパフォーマンスを改善したいと考えています。コードには 2 つの主要な部分があります。最初の IO 操作。(複数のセッション ID の Azure サービス バス キューからの読み取り)、2 番目のデータの処理 - CPU の負荷が高い。Task を返す async メソッドで DequeueAsync メソッドをラップしました。

private async Task<SomeReturnValue> AcceptFromQueueAsync(){
  try{ 
       SomeReturnValue result = await DequeueAsync.configureAwait(false);
       return SomeReturnValue;  
  }
  catch{
   //logging and stuff
  }

CPU 負荷の高い方法は同期です: DoSyncWork() 2 番目の部分は CPU 負荷が高いので、並列処理を使用したくありません (実際には使用できません...) CPU 部分は、IO 部分が終了したときにのみ開始できます。上記を考えると、次の実装は1つのCPUマシンで行う方法ですか?

private void AcceptAndProcessWrapper(){
    //Count is some cosnt defined outside the method
    _acceptTasks = new List<Task<SomeReturnValue>>();
     for (var i = 0; i < Count; i++)
     {
                    _acceptTasks.Add(AcceptFromQueueAsync());
      }
      //The use of list is for convince in processing  
      Task.WaitAll(_acceptTasks.ToArray());
      //The CPU part 
       Task.Run(DoSyncWork).Wait();
 }

同期部分に Task.Run() を使用できなかった可能性があることはわかっていますが、複数のコアで機能を実装できるようにしたい (Task.Run() を使用していくつかのタスクを開始し、それらを配列に保持することにより) 上記の実装は. (タスクを返す async メソッドを複数回呼び出すと) パフォーマンスが向上しますか? または、Task.Run(AcceptFromQueueAsync) などの非同期呼び出しごとに新しいタスクを開始する必要がありますか?

4

4 に答える 4

3

あなたが持っているコードは、実際に非同期デキューを並行して行います。すべての非同期タスクを一度に開始し、すべてが完了するまで待機して続行します。

余分な呼び出しを追加してTask.Runも役に立ちません。別のスレッドで非同期タスクを開始すると、付加価値がないために余分なオーバーヘッドが追加されるだけです。 別のスレッドでの非同期作業ではなく、別のスレッドでCPU バウンドの作業Task.Runを実行するために使用する必要があります。

于 2013-11-12T18:10:16.253 に答える
1

Task(s) のパフォーマンスについて言えば (将来的に で使用する場合) 、 はデフォルトで ThreadPoolDoSyncWorkを使用することにも留意する必要がありますが、Thread プールのスレッドは高速で小規模な作業を行うことが期待されます。Task.Runタスクが本当に「重い」ものである場合は、新しく作成されたスレッドでそれらを実行することを検討する必要があります。これは、次のように強制される場合もあります。

new Task(() => { }, TaskCreationOptions.LongRunning);

編集:

以下のコメットでいくつかの話をした後、もう少し整理したいと思います。

現在、Task.Run(DoSyncWork).Wait();実際には意味がありません (さらに、タスクを別のスレッド (ThreadPool のものであっても) で実行するには追加の時間がかかる場合がありますが、将来複数のコアを使用する場合は、明らかにそのタスクを別のスレッドに移動する必要があります)。実行するスレッド (実際に CPU を大量に使用する場合は、タスクを " LongRunning " として実行することを検討してください) (もちろん、アプリに必要な場合 (アプリの種類がわからない場合))。まだ.Wait()すぐに電話する必要はありません。

于 2013-11-12T18:14:27.487 に答える
0

最初の部分を非同期で実行することは意味があるかもしれませんが、名前に Async が含まれているため、とにかくブロックしないことを示唆しています。終了するのを待っています。

于 2013-11-12T18:09:50.110 に答える
0

これに似たパターンを使用して、IO と CPU を可能な限り維持しようとします。

public async void DoWork()
{
    Task cpuBoundTask = null;
    Task ioBoundTask = null;

    while(true)
    {
         ioBoundTask = DoIOBoundStuff();
         var ioResult = await ioBoundTask;

         if(cpuBoundTask != null)
         {
             await cpuBoundTask;
         }
         cpuBoundTask = DoCpuBoundStuff(ioResult);
    }
 }
于 2013-11-12T20:33:07.937 に答える