4

パフォーマンスを最適化するために、並列処理できる部分に簡単に分割できるタスクがあります。

独立して処理できるタスクの各部分を準備するプロデューサー アクターを作成しました。この準備は比較的安価です。

それぞれの独立したタスクを処理するコンシューマー アクターを作成しました。パラメータによっては、独立したタスクの各部分の処理に数秒かかる場合があります。すべてのタスクはまったく同じです。それらはすべて同じアルゴリズムを処理し、同じ量のデータ (もちろん値は異なります) を処理するため、処理時間はほぼ同じになります。

したがって、プロデューサーはコンシューマーよりもはるかに高速です。したがって、すぐに 200 または 2000 のタスクが準備される可能性があります (パラメーターによって異なります)。それらはすべてメモリを消費しますが、一度に実行できるのはほんの数個です。

これで、タスクを使用して処理するための 2 つの単純な戦略がわかりました。

  1. タスクごとに新しいコンシューマー アクター インスタンスを作成します。

    • 各コンシューマはタスクでのみ処理します。
    • 同時に多くのコンシューマー アクター インスタンスが存在すると想定していますが、一度に処理できるのはそのうちの 2 つだけです。
    • デフォルトのスケジューラはどのように機能しますか? 次の消費者がスケジュールされる前に、各消費者アクターは処理を終了できますか? または、コンシューマが中断されて別のコンシューマに置き換えられ、最初のタスクが完了するまでの時間が長くなりますか? このアクターのスケジューリングは、プロセスまたはスレッドのスケジューリングと同じではないと思いますが、中断にはまだいくつかの欠点があることは想像できます (例: キャッシュ ミスが増えるなど)。
  2. もう 1 つの戦略は、コンシューマー アクターの N インスタンスを使用し、処理するタスクをメッセージとしてそれらに送信することです。

    • 各コンシューマーは、複数のタスクを順番に処理します。
    • N (消費者数) の適切な値を見つけるのは私に任されています。
    • N 個のコンシューマーに対するタスクの分散も私に任されています。
  3. プロデューサーとコンシューマーの間でより多くの調整が行われる、より洗練されたソリューションを想像することもできますが、スケジューラーに関する知識がなければ、適切な決定を下すことはできません。

手動の解決策でパフォーマンスが大幅に向上しない場合は、(戦略 1 のように) スケジューリング タスクが私に任されていないデフォルトの解決策 (Scala の世界の一部によって提供される) をお勧めします。

質問のまとめ:

  • デフォルトのスケジューラはどのように機能しますか?
    • 次の消費者がスケジュールされる前に、各消費者アクターは処理を終了できますか?
    • または、コンシューマが中断されて別のコンシューマに置き換えられ、最初のタスクが完了するまでの時間が長くなりますか?
    • スケジューラーが頻繁にアクターに割り込んで別のアクターをスケジュールする場合の欠点は何ですか? キャッシュミス?
    • この中断とスケジューリングは、プロセス スケジューリングまたはスレッド スケジューリングのコンテキスト変更のようなものでしょうか?
  • これらの戦略を比較して、他に利点や欠点はありますか?
  • 特に、戦略 1 には戦略 2 よりも不利な点がありますか?
  • これらの戦略のどれが最適ですか?
  • 私が提案したよりも優れた戦略はありますか?

残念ながら、最後の 2 つのような質問には絶対に答えることはできませんが、今回は可能な限り具体的なケースを挙げようとしたので、おそらくこれは可能です。

他の質問はあまり議論しなくても答えられると思います。これらの答えがあれば、要件に最適な戦略を選択できるはずです。

私は自分でいくつかの調査と考えを行い、いくつかの仮定を思いつきました。これらの仮定のいずれかが間違っている場合は、教えてください。

4

3 に答える 3

0

私があなただったら、2ndオプションを先に進めたでしょう。タスクごとに新しいアクター インスタンスを作成するのは面倒です。また、 の賢明な決定によりN、完全なシステム リソースを使用できます。

これは完全な解決策ではありませんが。しかし、可能なオプションの 1 つは、プロデューサーがタスクの生成速度を停止/減速できないかということです。これは理想的です。利用可能なコンシューマーまたは何かがある場合にのみ、プロデューサーはより多くのタスクを生成します。

于 2012-11-26T11:13:41.503 に答える
0

このような単純なタスクでは、アクターはまったく利益を上げません。プロデューサーを Thread として実装し、各タスクを Runnable として実装します。タスクを実行するには、java.util.concurrent のスレッド プールを使用します。java.util.concurrent を使用します。準備され実行中のタスクの数を制限するためのセマフォ: 次のタスクを作成する前に、プロデューサーはセマフォを取得し、各タスクは実行の最後にセマフォを解放します。

于 2012-11-28T02:39:45.707 に答える