このナンセンスを私に説明してもらえますか?基本的に配列を数学演算で埋めるメソッドがあります。I/Oなどはありません。現在、このメソッドの実行には約50秒かかり、コードは完全にスケーラブル(理論的には100%)なので、4つのスレッドに分割し、それらが完了するのを待って、4つの配列を再アセンブルします。今、私はクアッドコアプロセッサでプログラムを実行し、約15秒かかると予想していますが、実際には58秒かかります。そうです:時間がかかります!CPUが100%動作しているのがわかります。また、各スレッドが計算の1/4を実行し、スレッドの作成と配列の再アセンブルに合計で約1〜2ミリ秒かかることを知っています。このようなパフォーマンスの低下の原因は何ですか?CPUはその間何をしているのですか?コード: http: //pastebin.com/cFUgiysw
4 に答える
スレッドはそのようには機能しません。
スレッドは引き続き同じプロセスの一部であるため(OSによって異なります)、オペレーティングシステムの観点から、CPU時間は1プロセスの1スレッドの場合と同じように1プロセスの4スレッドに対してスケジュールされます。
また、値の数が非常に少ないため、オーバーヘッドの真っ只中にスケーラビリティが見られません。Javaで配列を再アセンブルするにはコストがかかります。
「コンテキスト切り替えのオーバーヘッド」のようなものをチェックしてください-理論を実践にマッピングしようとすると、そのようなものは常にあなたを混乱させます:P
私はシングルスレッドの方法に固執します:)
〜ダン
新しいスレッドを開くことに関連するコストがあります。最大8秒になるとは思いませんが、使用しているスレッドによって異なります。一部のスレッドは、スレッドセーフにするために処理しているデータのコピーを作成する必要があり、これには時間がかかる場合があります。このコストは一般にオーバーヘッドと呼ばれます。実行している実行がシリアル化できない場所である場合、たとえば同じファイルを読み取る場合や共有リソースへのアクセスが必要な場合、スレッドは互いに待機する必要があります。これには時間がかかる場合があり、最適でない条件下では、シリアル実行よりも時間がかかる場合があります。 。私のヒントは、これらのシリアル化できないイベントをチェックして、可能であればスレッド部分からそれらを削除することです。また、スレッドの数を減らしてみてください。4CPUに対して4スレッドが常に最適であるとは限りません。
それが役に立てば幸い。
あなたが何をしているのか、そしてどのように仕事を分割しているかに大きく依存します。この問題には多くの原因が考えられます。
- 最も可能性の高い原因は、CPU のすべての帯域幅を 1 つのスレッドでメイン メモリ バスに使用していることです。これは、データ セットが CPU キャッシュよりも大きい場合に発生する可能性があります。特にランダムアクセス動作がある場合。キャッシュ チャーンを減らすために、複数のコピーを取得するのではなく、元の配列を再利用することを検討できます。
- ロックのオーバーヘッドは、パフォーマンスの向上よりも大きくなります。私はあなたが非常にコースロックを使用していると思うので、これは問題にならないはずです.
- スレッドの停止を開始するには時間がかかりすぎます。あなたのコードは数秒であるため、これも疑問です。
常にスレッドを作成して強制終了していない限り、スレッドのオーバーヘッドは問題になりません。同時に実行される 4 つのスレッドは、スケジューラーにとって大した問題ではありません。
Peter Lawrey が示唆したように、メモリ帯域幅が問題になる可能性があります。50 秒のコードは Java エンジンで実行されており、両者は利用可能なメモリ帯域幅をめぐって競合しています。Java エンジンは、コードを実行するためにメモリ帯域幅を必要とし、コードは計算を行うためにそれを必要とします。
コードがコンパイルされた場合に当てはまる「完全にスケーラブル」と記述します。Javaエンジンで実行されるため、これは当てはまりません。したがって、全体的な時間の 16% の増加は、1 つのスレッドの滑らかさと、メモリ アクセスで衝突する 4 つのスレッドの混乱との違いとして見ることができます。