メインスレッドで何かを実行する1スレッドのコードがあり、約10〜20ミリ秒かかるとします。プロセッサの2つのコアを利用して、異なるコアにある2つのスレッドのタスクを分割したいと思います。技術的には、おそらく2つのスリープスレッドを再開し、それらが完了するまでスリープ状態にして、再びスリープ状態にする必要があります。タスクが実行するのに十分な長さであれば、何も怖いことはありません。しかし、10〜20ミリ秒の間、よく知られた同期技術を使用することのペナルティは、私にかなりの時間を費やすことになると思います。私があまりにも疑わしく、Windows / CPUがすべてのスリープ/ウェイクアップ要求を効果的にするのに良い仕事をしている場合、1ms、10ms、100msの分割がまだ理にかなっている最短時間はどれくらいですか?
3 に答える
既存のスレッドプール (既存のスリープ状態のスレッド) を使用したマルチスレッドは、10 ~ 20 ミリ秒の操作を高速化できます。
スレッドをウェイクアップしてスレッドに参加するための特定の同期呼び出しは非常に小さく、1 ミリ秒をはるかに下回ります。
注意すべきことの 1 つは、参照の局所性です。複数のスレッドで実行されているコードが同じメモリにアクセスしている場合、CPU はメモリ アクセスを同期する必要があり、実際のパフォーマンスの向上が低下する可能性があります。
同様に、スレッドが共通のリソースを使用していて、ロックやその他のスレッド同期が必要な場合、これらのロックを待機するとパフォーマンスが低下します。
これらのスレッドに I/O がある場合、それを複数のスレッドに分割すると、最も高速になります。
この短いタスクが何度も呼び出されない限り (つまり、ループ内で) 意味がありません。なぜなら、タスクの切り替え/スレッドの開始/同期を考慮する前でも、せいぜい 10 ミリ秒の処理時間を節約できるからです...
多くのタスクがあり、作業中のスレッドが (ExecutorService のように) 共通キューから継続的にタスクを受け取る場合、タスクのオーバーヘッドは 1..10 マイクロ秒です。Fork/Join 機能はさらに効果的です。スレッドの切り替えは最もコストのかかるアクションであるため、2 つのスリープ状態のスレッドを再開してマスター スレッドを待機させるのではなく、マスター スレッドで 1 つのタスクを実行し、ワーカー スレッドで 1 つのタスクのみを実行することをお勧めします。