シナリオ:サンプルアプリケーションがあり、3つの異なるシステム構成がある-
- 2 core processor, 2 GB RAM, 60 GB HHD,
- 4 core processor, 4 GB RAM, 80 GB HHD,
- 8 core processor, 8 GB RAM, 120 GB HHD
私のアプリケーションのH/W機能を効果的に活用するために、noを構成したいと思います。アプリケーションレベルでのスレッドの数。ただし、システム機能を完全に理解した後でのみ、これを実行したいと思います。
最大と最小の番号を参照してシステムの能力を決定するいくつかの方法(system/modus/tool)がありますか?スレッドの効率とパフォーマンスを損なうことなく最適にサービスできます。これにより、完全な正義を行い、それぞれのハードウェア構成で最高のパフォーマンスを実現するアプリケーションの値のみを構成できます。
Edited1:特定のハードウェア構成のベースラインを設定する方法について、詳細を教えてください。
Edited2:より直接的にするために-一般的な/全体的なレベルでのスレッドのCPU管理について理解するために私が読むことができるリソース/記述について学習/知っておきたい。
使用するスレッドの最適数は、いくつかの要因に依存しますが、ほとんどの場合、使用可能なプロセッサーの数と、タスクがCPUをどれだけ集中させるかです。 Java Concurrency in Practice は、最適なスレッド数を推定するために次の公式を提案します。
_N_threads = N_cpu * U_cpu * (1 + W / C)
_
どこ:
Runtime.getRuntime().availableProcessors();
から取得できるプロセッサーの数です。したがって、たとえば、CPUにバインドされたシナリオでは、CPUと同じ数のスレッドがあります(その数+ 1を使用することを提唱する人もいますが、大きな違いがあることは知りません)。
遅いI/Oプロセス、たとえばWebクローラーの場合、ページのダウンロードがページの処理よりも10倍遅い場合、W/Cは10になる可能性があります。この場合、100スレッドを使用すると便利です。
ただし、実際には上限があることに注意してください(10,000スレッドを使用しても通常はスピードアップしません。通常のメモリ設定ですべてを開始する前にOutOfMemoryErrorが発生する可能性があります)。
これはおそらく、アプリケーションが実行される環境について何も知らない場合に取得できる最良の見積もりです。本番環境でアプリケーションをプロファイリングすると、設定を微調整できる場合があります。
厳密に関連しているわけではありませんが、プログラムの並列化によって期待できる最大のスピードアップを測定することを目的とする アムダールの法則 にも興味があるかもしれません。
マシンごとのスレッド数を割り当てるための構成およびコマンドラインスイッチを提供することをお勧めします。ユーザー/管理者が明示的に異なる方法でアプリケーションを構成していない場合は、他の回答で示されているように、Runtime.getRuntime()。availableProcessors()に基づくヒューリスティックを使用します。私はstronglyいくつかの理由により、スレッドからコアへのヒューリスティックベースの排他的推測を推奨しません。
最近のほとんどのハードウェアは、あいまいなタイプの「ハードウェアスレッド」へと移行しています。IntelのハイパースレッディングやAMDのコンピュートモジュールなどのSMTモデルは式を複雑にし(詳細は以下)、実行時にこの情報をクエリすることは難しい場合があります。
最新のハードウェアには、アクティブなコアと周囲温度に基づいて速度をスケーリングするターボ機能があります。ターボ技術が向上するにつれて、速度(ghz)の範囲が拡大します。最近のIntelおよびAMDチップの一部は、2.6 GHz(すべてのコアがアクティブ)から3.6 GHz(シングル/デュアルコアがアクティブ)の範囲であり、SMTと組み合わせると、以前の設計では各スレッドが1.6 GHz〜2.0 GHzのスループットを効果的に得ることができます。現在、実行時にこの情報をクエリする方法はありません。
アプリケーションがターゲットシステムで実行される唯一のプロセスであるという強力な保証がない場合、すべてのCPUリソースを盲目的に消費しても、ユーザーまたはサーバーの管理者が気に入らない場合があります(ソフトウェアがユーザーアプリかサーバーアプリかによって異なります)。 。
オペレーティングシステム全体を独自のホームロールマルチタスクカーネルに置き換えることなしに、実行時にマシンの残りの部分で何が起こっているかを知るための確実な方法はありません。ソフトウェアは、プロセスにクエリを実行し、CPU負荷などを調べることにより、知識に基づいた推測を試みることができますが、そうすることは複雑であり、有用性は特定のタイプのアプリケーション(ユーザーが適格とする可能性がある)に限定され、通常、昇格または特権の恩恵を受けるか必要とするアクセスレベル。
現代のウイルススキャナーは、現代のオペレーティングシステムによって提供される特別な優先順位フラグを設定することで、現在機能しています。彼らは、「システムがアイドル状態」であることをOSに通知させます。 OSは、CPU負荷だけでなくその決定に基づいています。また、映画プレーヤーなどによって設定された可能性のあるユーザー入力やマルチメディアフラグも考慮します。これは、ほとんどアイドルのタスクには適していますが、次のようなCPUを多用するタスクには役立ちません。あなたのもの。
分散型ホームコンピューティングアプリ(BOINC、Folding @ Homeなど)は、実行中のプロセスとシステムのCPU負荷を定期的に(おそらく1秒または0.5秒に1回)クエリすることで機能します。アプリに属していないプロセスで、複数のクエリが連続してロードが検出された場合、アプリは計算を一時停止します。いくつかのクエリで負荷が低くなると、再開します。 CPU負荷の読み出しは短時間のスパイクで悪名高いため、複数のクエリが必要です。まだ注意点があります:1.ユーザーは、BOINCを自分のマシンの仕様に合うように手動で再構成することをお勧めします。 2. BOINCが管理者権限なしで実行されている場合、他のユーザーによって開始されたプロセス(一部のサービスプロセスを含む)を認識しないため、CPUリソースの競合と不当に競合する可能性があります。
SMT(ハイパースレッディング、計算モジュール)について):
最近のほとんどのSMTは、ハードウェアコアまたはスレッドとしてレポートしますが、SMTシステムのすべてのコアにまたがってスケーリングされたときに最適に動作するアプリケーションはほとんどないため、通常は適切ではありません。さらに悪いことに、コアが共有されている(SMT)か専用であるかのクエリを実行しても、期待した結果が得られないことがよくあります。場合によっては、OS自体が単に知らないこともあります(たとえば、Windows 7はAMD Bulldozerの共有コア設計を認識していません)。信頼できるSMTカウントを取得できる場合、経験則では、各SMTを、CPU集中型のタスクではスレッドの半分として、ほとんどアイドルのタスクではスレッド全体としてカウントします。しかし実際には、SMTの重みは、どのような計算を行うか、およびターゲットアーキテクチャによって異なります。たとえば、IntelとAMDのSMT実装は、互いにほぼ逆の動作をします。たとえば、Intelは、整数演算と分岐演算がロードされたタスクの並列実行に優れています。 AMDは、SIMDとメモリ操作を並行して実行することに長けています。
ターボ機能について:
最近のほとんどのCPUには非常に効果的な組み込みのターボサポートがあり、システムのすべてのコアにわたるスケーリングから得られる価値がさらに減少します。さらに悪いことに、ターボ機能は、CPU負荷と同じくらいシステムの実際の温度に基づいている場合があるため、タワー自体の冷却システムは、CPU仕様と同じくらい速度に影響します。たとえば、特定のAMD A10(ブルドーザー)では、2つのスレッドで3.7 GHzで実行されていることがわかりました。 3番目のスレッドが開始されると3.5ghzに低下し、4番目のスレッドが開始されると3.4ghzに低下しました。統合されたGPUでもあるため、4つのスレッドとGPUが動作していると、約3.0ghzまで低下しました(A10 CPUは、高負荷シナリオで内部的にGPUを優先します)。しかし、2つのスレッドとGPUがアクティブな場合でも、3.6ghzを必要とします。私のアプリケーションはCPUとGPUの両方を使用していたため、これは重要な発見でした。プロセスを2つのCPUバウンドスレッドに制限することで、全体的なパフォーマンスを向上させることができました(他の2つの共有コアは引き続き役に立ちましたが、それらはGPUサービススレッドとして機能し、ウェイクアップしてGPUへの新しいデータのプッシュにすばやく応答でき、必要に応じて)。
...しかし、同時に、4xスレッドでのアプリケーションは、高品質の冷却装置が取り付けられたシステムではるかに優れたパフォーマンスを発揮した可能性があります。それはすべて非常に複雑です。
結論:良い答えはありません。CPUSMT /ターボ設計の分野は進化し続けているため、近いうちに良い答えがあるとは思えません。今日策定する適切なヒューリスティックは、明日には理想的な結果を生み出さない場合があります。だから私の推奨は、それに多くの時間を無駄にしないことです。コア数に基づいて、ローカルの目的に十分に合うものをおおまかに推測し、config/switchでオーバーライドできるようにして、次に進みます。
次のようにして、JVMで利用可能なプロセッサの数を取得できます。
Runtime.getRuntime().availableProcessors()
ただし、利用可能なプロセッサの数から最適なスレッド数を計算することは、残念ながら簡単ではありません。これは、アプリケーションの特性に大きく依存します。たとえば、CPUにバインドされたアプリケーションでは、プロセッサの数よりも多くのスレッドを使用することはほとんど意味がありませんが、アプリケーションがほとんどIOにバインドされている場合は、より多くのスレッドを使用することができます。他のリソースを大量に消費するプロセスがシステムで実行されている場合も考慮する必要があります。
最善の戦略は、ハードウェア構成ごとに経験的に最適なスレッド数を決定し、それらの数をアプリケーションで使用することだと思います。
ここでは、推測によるアプローチを推奨し、デフォルトを上書きするための構成を提供する他の回答に同意します。
さらに、アプリケーションが特にCPUを集中的に使用する場合は、アプリケーションを特定のプロセッサに「固定」することを検討する必要があります。
プライマリオペレーティングシステムが何であるか、または複数のオペレーティングシステムをサポートしているかどうかは言いませんが、ほとんどの場合、これを行う方法があります。たとえば、Linuxには taskset があります。
一般的なアプローチは、CPU 0(常にOSによって使用される)を回避し、アプリケーションのCPUアフィニティを同じソケットにあるCPUのグループに設定することです。
アプリのスレッドをcpu 0から離しておくと(可能であれば、他のアプリケーションから離して)、タスクの切り替え量を減らすことでパフォーマンスが向上することがよくあります。
アプリケーションを1つのソケットに保持すると、アプリのスレッドがCPU間で切り替わるときにキャッシュの無効化が減少するため、パフォーマンスがさらに向上します。
他のすべてと同様に、これは、実行しているマシンのアーキテクチャー、および他のアプリケーションが実行しているものに大きく依存します。
VisualVm ツールを使用してスレッドを監視します。最初にプログラム内に最小スレッドを作成し、そのパフォーマンスを確認します。次に、プログラム内のスレッド数を増やし、再びそのパフォーマンスを分析します。これが役立つ場合があります。
私はこれを使用してPythonスクリプトを使用してコア(およびメモリなど)の数を決定し、Javaアプリケーションを最適なパラメータと人間工学に基づいて起動します。- Github上のPlatformWise
これは次のように機能します。上記のスクリプトでgetNumberOfCPUCores()
を呼び出してコアの数を取得し、getSystemMemoryInMB()
を取得するpythonスクリプトを記述して、 RAM:コマンドライン引数を介してその情報をプログラムに渡すことができ、プログラムはコアの数に基づいて適切な数のスレッドを使用できます。
ただし、使用可能なプロセッサの数から最適なスレッド数を計算することは、残念ながら簡単ではありません。これは、アプリケーションの特性に大きく依存します。たとえば、CPUにバインドされたアプリケーションでは、プロセッサの数よりも多くのスレッドを使用することはほとんど意味がありませんが、アプリケーションがほとんどIOにバインドされている場合は、より多くのスレッドを使用することができます。他のリソース集約型プロセスがシステムで実行されている場合も考慮する必要があります。
アプリケーションレベルでのスレッドの作成は適切であり、マルチコアプロセッサでは、パフォーマンスを向上させるためにコアで個別のスレッドが実行されます。コアの処理能力を利用するには、スレッド化を実装するのがベストプラクティスです。
私が思うこと:
したがって、開発中のアプリケーションには、スレッドレベル<=コアの数がない必要があります。
スレッドの実行時間はオペレーティングシステムによって管理され、非常に予測不可能なアクティビティです。 CPU実行時間は、タイムスライスまたはクォンタムと呼ばれます。作成するスレッドが増えると、オペレーティングシステムはこのタイムスライスの一部を使用して、最初に実行するスレッドを決定するため、各スレッドが取得する実際の実行時間を短縮できます。言い換えると、多数のスレッドがキューに入れられている場合、各スレッドの処理は少なくなります。
これを読んで、実際にCPUコアを活用する方法を入手してください。素晴らしいコンテンツ。 csharp-codesamples.com/2009/03/threading-on-multi-core-cpus/