6

そこで、スレッドを使っていくつかのベンチマーク テストを行っていて、次のコードを書きました。

resp_threadless[] と resp_threaded[] はグローバル int 配列で、サイズは n です。

int n = 100000;

void function() {
  for (long j = 0; j < n; ++j) {
    int count = 0;
    double x = vetor[j];
      while (x > 1.0) {
      x = sqrt(x);
      ++count;
    }
   resp_threadless[j] = count;
  }
}

DWORD WINAPI function_th( LPVOID lpParam ) {
for (long j = 0; j < n; ++j) {
    int count = 0;
    double x = vetor[j];
      while (x > 1.0) {
      x = sqrt(x);
      ++count;
    }
   resp_threadless[j] = count;
  }
}

彼女を呼び出すだけで、最初の関数のベンチマークを行いました。

function();

そして、次のような2番目のもの:

HANDLE hThreadArray[1];
DWORD dwThreads[1];
hThreadArray[0] = CreateThread(NULL, 0, function_th, NULL , 0, &(dwThreads[0]));
WaitForMultipleObjects(1, hThreadArray, TRUE, INFINITE);
CloseHandle(hThreadArray[0]);

function_th() を使用して複数のスレッドを呼び出しても並列化されないことを知っていることに注意してください。これは、本当に奇妙な結果が得られたため、単なるテストであるため、同じコードを使用して 1 つのスレッドと 1 つの関数で何が起こるかを確認することにしました。 .

Intel Atom N270 と NUMPROC = 1 の Windows XP でこれをテストしました。

結果: シリアル コード: 1485 ミリ秒 1 つのスレッド: 425 ミリ秒

マルチプロセッサ マシンを使用して同様の結果を得たことがあります。また、セマフォを使用してスレッドによって実行される作業を並列化するコードでも同様の結果が得られました。

何が起こっているのか誰にもわかりませんか?

編集

順序を逆にする、それぞれ複数回実行するなど... ->変更なし

より高い N -> スレッド 1 は比例してさらに高速になります

QueryPerformanceCounter() を使用 -> 変更なし

スレッド作成のオーバーヘッド -> スレッド化を 1 つでも遅くする必要がありますが、高速ではありません

元のコード: http://pastebin.com/tgmp5p1G

4

1 に答える 1

2

それはcache hit問題です。質問で説明した順序でベンチマークを行ったと思われます。関数が最初に呼び出され、スレッドが後で呼び出されました。これをより詳細にベンチマークすると、理由がわかります。データ (sqrt) がキャッシュで利用できるため、コードの実行速度が大幅に向上します。 証明するテスト:

  1. function()スレッドを呼び出す前に、 を 2 回以上実行してください。関数への 2 番目の呼び出しは、より迅速な結果を既に提供します。
  2. 関数の前にスレッドを呼び出すと、結果は反対になります。関数はより良い結果を示します。

理由: すべての sqrt 計算 (または少なくともそれらの多く) がキャッシュで利用可能であり、再計算する必要はありません。それはずっと速いです。

于 2012-10-22T07:56:03.650 に答える