10

カーネルオブジェクトを使用して異なるCPUで実行されているスレッドを同期する場合、他のOSと比較してWindows Server 2008 R2を使用すると、実行時のコストが増える可能性がありますか?

編集:そして、回答からわかるように、質問には「より低いCPU使用率レベルで実行している場合」というフレーズも含める必要があります。私はこの質問に対する私自身の答えにもっと多くの情報を含めました。

バックグラウンド

プロセス間の通信に共有メモリとセマフォを使用する製品に取り組んでいます(2つのプロセスが同じマシンで実行されている場合)。Windows Server 2008 R2(この後Win2008R2に短縮)のパフォーマンスの問題の報告により、Win2008R2の2つのスレッド間でセマフォを共有するのが他のOSに比べて比較的遅いことがわかりました。

それを再現する

次のコードを2つのスレッドで同時に実行することで、それを再現することができました。

for ( i = 0; i < N; i++ )
  {
  WaitForSingleObject( globalSem, INFINITE );
  ReleaseSemaphore( globalSem, 1, NULL );
  }

Windows Server 2003R2SP2とWindowsServer2008 R2をデュアルブートするマシンでテストすると、上記のスニペットはWin2003R2マシンでWin2008R2と比較して約7倍高速に実行されます(Win2003R2では3秒、Win2008R2では21秒)。

テストの簡単なバージョン

以下は、前述のテストの完全版です。

#include <windows.h>
#include <stdio.h>
#include <time.h>


HANDLE gSema4;
int    gIterations = 1000000;

DWORD WINAPI testthread( LPVOID tn )
{
   int count = gIterations;

   while ( count-- )
      {
      WaitForSingleObject( gSema4, INFINITE );
      ReleaseSemaphore( gSema4, 1, NULL );
      }

   return 0;
}


int main( int argc, char* argv[] )
{
   DWORD    threadId;
   clock_t  ct;
   HANDLE   threads[2];

   gSema4 = CreateSemaphore( NULL, 1, 1, NULL );

   ct = clock();
   threads[0] = CreateThread( NULL, 0, testthread, NULL, 0, &threadId );
   threads[1] = CreateThread( NULL, 0, testthread, NULL, 0, &threadId );

   WaitForMultipleObjects( 2, threads, TRUE, INFINITE );

   printf( "Total time = %d\n", clock() - ct );

   CloseHandle( gSema4 );
   return 0;
}

詳細

テストを更新して、スレッドが1回の反復を実行し、各ループで次のスレッドに強制的に切り替えるようにしました。各スレッドは、各ループの最後で実行するように次のスレッドに信号を送ります(ラウンドロビンスタイル)。また、セマフォ(カーネルオブジェクト)の代わりにスピンロックを使用するように更新しました。

私がテストしたすべてのマシンは64ビットマシンでした。テストは主に32ビットとしてコンパイルしました。64ビットとして構築された場合、全体的に少し速く実行され、比率がいくらか変更されましたが、最終的な結果は同じでした。Win2008R2に加えて、Windows 7 Enterprise SP 1、Windows Server 2003 R2 Standard SP 2、Windows Server 2008(R2ではない)、およびWindows Server2012Standardに対しても実行しました。

  • 単一のCPUでのテストの実行は、大幅に高速化されました(SetThreadAffinityMaskでスレッドアフィニティを設定し、 GetCurrentProcessorNumberでチェックすることで「強制」されました)。当然のことながら、単一のCPUを使用すると、すべてのOSで高速になりましたが、カーネルオブジェクトの同期を使用したマルチCPUとシングルCPUの比率は、Win2008R2の方がはるかに高かった。Win2008R2を除くすべてのマシンの一般的な比率は2倍から4倍でした(複数のCPUでの実行には2倍から4倍の時間がかかりました)。しかし、Win2008R2では、比率は9倍でした。
  • ただし...すべてのWin2008R2マシンで速度低下を再現することはできませんでした。私は4でテストしました、そしてそれはそれらのうちの3つで現れました。ですから、これに影響を与える可能性のある何らかの構成設定やパフォーマンス調整オプションがあるのではないかと思わずにはいられません。パフォーマンスチューニングガイドを読み、さまざまな設定を確認し、さまざまな設定(バックグラウンドサービスとフォアグラウンドアプリなど)を変更しましたが、動作に違いはありません。
  • 必ずしも物理コア間の切り替えに関係しているとは限りません。私は当初、異なるコア上のグローバルデータに繰り返しアクセスするコストに何らかの形で関係しているのではないかと思っていました。ただし、同期に単純なスピンロック(カーネルオブジェクトではない)を使用するバージョンのテストを実行する場合、さまざまなCPUで個々のスレッドを実行すると、すべてのOSタイプでかなり高速になりました。マルチCPUセマフォ同期テストとマルチCPUスピンロックテストの比率は、通常10倍から15倍でした。しかし、Win2008R2 Standard Editionマシンの場合、比率は30倍でした。

更新されたテストの実際の数値は次のとおりです(時間はミリ秒単位です)。

+----------------+-----------+---------------+----------------+
|       OS       | 2 cpu sem |   1 cpu sem   | 2 cpu spinlock |
+----------------+-----------+---------------+----------------+
| Windows 7      | 7115 ms   | 1960 ms (3.6) | 504 ms (14.1)  |
| Server 2008 R2 | 20640 ms  | 2263 ms (9.1) | 866 ms (23.8)  |
| Server 2003    | 3570 ms   | 1766 ms (2.0) | 452 ms (7.9)   |
+----------------+-----------+---------------+----------------+

テストの2つのスレッドは、それぞれ100万回の反復を実行しました。これらの精巣はすべて同一のマシンで実行されました。Win Server2008およびServer2003の番号は、デュアルブートマシンからのものです。Win 7マシンの仕様はまったく同じですが、物理マシンは異なります。この場合のマシンは、Corei5-2520M2.5GHzを搭載したLenovoT420ラップトップです。明らかにサーバークラスのマシンではありませんが、実際のサーバークラスのハードウェアでも同様の結果が得られます。括弧内の数字は、指定された列に対する最初の列の比率です。

この1つのOSがCPU間のカーネルレベルの同期に余分な費用を導入するように見える理由について何か説明はありますか?または、これに影響を与える可能性のある構成/調整パラメーターを知っていますか?

これは非常に冗長で長い投稿になりますが、必要に応じて、上記の番号から取得したテストコードの拡張バージョンを投稿することもできます。これは、ラウンドロビンロジックとスピンロックバージョンのテストの実施を示しています。

拡張された背景

なぜこのように行われるのかについての避けられない質問のいくつかに答えようとすること。そして、私は同じです...私が投稿を読んだとき、私はしばしば私がなぜ尋ねているのか疑問に思います。だからここにいくつかの試みが明確になります:

  • アプリケーションは何ですか?データベースサーバーです。状況によっては、顧客はサーバーと同じマシンでクライアントアプリケーションを実行します。その場合、(ソケットよりも)通信に共有メモリを使用する方が高速です。この質問は、共有メモリ通信に関連しています。
  • ワークロードは本当にイベントに依存していますか?ええと...共有メモリ通信は名前付きセマフォを使用して実装されています。クライアントはセマフォに信号を送り、サーバーはデータを読み取り、応答の準備ができたらサーバーはクライアントにセマフォに信号を送ります。他のプラットフォームでは、目がくらむほど速くなります。Win2008R2では、そうではありません。また、お客様のアプリケーションにも大きく依存します。彼らがサーバーへの小さなリクエストをたくさん使ってそれを書いた場合、2つのプロセスの間にはたくさんのコミュニケーションがあります。
  • 軽量ロックは使用できますか?おそらく。私はすでにそれを見ています。しかし、それは元の質問とは無関係です。
4

4 に答える 4

3

コメントから回答に引き出されました:

サーバーが高性能電源プランに設定されていない可能性がありますか?Win2k8のデフォルトは異なる場合があります。多くのサーバーはデフォルトではありません、そしてこれはパフォーマンスに非常に大きな打撃を与えます。

OPはこれを根本的な原因として確認しました。

これは、この動作の面白い原因です。まったく違うことをしていると、頭の中で思い浮かびました。

于 2013-01-21T23:46:06.717 に答える
0

OSのインストール構成が異なる可能性があります。おそらく、遅いシステムは、同時にスケジュールされているプロセスから複数のスレッドを許可しないように構成されています。他の優先度の高いプロセスを常に(またはほとんど)実行する準備ができている場合、唯一の代替手段は、スレッドを並列ではなく順次実行することです。

于 2013-01-18T17:51:10.323 に答える
0

過度に長いOPに埋めるのではなく、この追加の「回答」情報をここに追加します。@usrは、電源管理オプションの提案で私を正しい方向に向けました。OPでの不自然なテストと元の問題には、異なるスレッド間での多くのハンドシェイクが含まれます。実世界のアプリでのハンドシェイクはさまざまなプロセスにまたがっていましたが、テストの結果、ハンドシェイクを実行しているのがスレッドまたはプロセスであるかどうかにかかわらず、結果に違いはありませんでした。CPU間でのセマフォ(カーネル同期オブジェクト)の共有は、Windows Server 2008 R2では、CPU使用率が低い(たとえば、5%から10%)場合の電力設定によって大きく影響を受けるようです。この時点での私の理解は、純粋に測定とタイミングのアプリケーションに基づいています。

Serverfaultに関する関連する質問では、これについても説明しています。

テスト設定

OSの電源オプションの設定WindowsServer2008R2のデフォルトの電源プランは「バランス」です。これを「HighPerformance」オプションに変更すると、このテストのパフォーマンスが大幅に向上しました。特に、「高度な電源設定の変更」で指定した設定が重要なようです。詳細設定には、プロセッサの電力管理の下に、最小プロセッサ状態と呼ばれるオプションがあります。バランスプランでのこれのデフォルト値は5%のようです。私のテストでそれを100%に変更することが重要でした。

BIOS設定さらに、BIOS設定はこのテストに大きな影響を与えました。これはハードウェアによって大きく異なると思いますが、テストしたプライマリマシンには「CPUPowerManagement」という名前の設定があります。BIOS設定の説明は、「システムアクティビティがないときにマイクロプロセッサクロックを自動的に停止(原文のまま)する省電力機能を有効または無効にする」です。 このオプションを「無効」に変更しました。

経験的結果

示されている2つのテストケースは次のとおりです。

  • (シンプルな。OPに含まれているものの修正バージョン。この単純なテストでは、2つのCPU上の2つのスレッド間の反復ごとにラウンドロビン切り替えを実施しました。各スレッドは100万回の反復を実行しました(したがって、CPU全体で200万回のコンテキストスイッチがありました)。
  • (b)実世界。クライアントが共有メモリを介してサーバーに多くの「小さな」要求を行い、グローバルな名前付きセマフォと同期していた実際のクライアント/サーバーテスト。

3つのテストシナリオは次のとおりです。

  • (i)バランスが取れている。バランスの取れた電源プランを使用するWindowsServer2008R2のデフォルトのインストール。
  • (ii)HighPerf。電源オプションを「バランス」から「ハイパフォーマンス」に変更しました。同様に、上記の[Minimum Processor State CPU]オプションを100%(5%から)に設定しても、同じ結果が発生しました。
  • (iii)BIOS。上記のようにCPU電源管理BIOSオプションを無効にし、[高性能電源]オプションも選択したままにしました。

表示される時間は秒単位です。

╔════════════════╦═════════════╦═══════════════╦════════════╗
║                ║ (i)Balanced ║ (ii) HighPerf ║ (iii) BIOS ║
╠════════════════╬═════════════╬═══════════════╬════════════╣
║ (a) Simple     ║ 21.4 s      ║ 9.2 s         ║ 4.0 s      ║
║ (b) Real World ║ 9.3 s       ║ 2.2 s         ║ 1.7 s      ║
╚════════════════╩═════════════╩═══════════════╩════════════╝

したがって、両方の変更(OSとBIOS)が行われた後、実際のテストと考案されたテストの両方が、デフォルトのインストールとデフォルトのBIOS設定よりも約5倍速く実行されました。


これらのケースをテストしているときに、説明できない結果に遭遇することがありました。CPUがビジー状態の場合(一部のバックグラウンドプロセスが起動する場合)、テストはより高速に実行されます。私はそれを頭の中で整理し、しばらく戸惑いました。しかし、今ではそれは理にかなっています。別のプロセスが実行されると、CPU使用率が、高電力状態を維持するために必要なしきい値を超えて増加し、コンテキストスイッチが高速になります。どの側面が遅いのかはまだわかりませんが(主なコストはWaitForSingleObject呼び出しに埋もれています)、最終結果はすべて意味があります。

于 2013-01-22T00:57:14.470 に答える
-3

これは妥当なベンチマークではありません。セマフォは常に同じプロセスで(おそらく同じCPU /コアで)フロブされます。実際のケースでのロックのコストの重要な部分は、異なるCPU /コアがメモリ領域への排他的アクセス(キャッシュ間を行き来する)をめぐって争うときに関係するメモリアクセスです。いくつかのより現実的なベンチマーク(申し訳ありませんが、私の領域ではありません)を探してください。o(さらに良い)アプリケーションを(考案されたが現実的な)テストデータで測定(いくつかの削減バージョン)します。

[ベンチマークのテストデータは、テストまたは回帰テストのデータであってはなりません。後の(おそらくほとんど使用されない)コーナーケースで、ベンチマークの「典型的な」実行が必要です。]

于 2013-01-20T01:38:03.793 に答える