新しいLinuxカーネルでは、コンテキストの切り替えが非常に遅くなります


99

サーバーのOSをUbuntu 10.04 LTSからUbuntu 12.04 LTSにアップグレードする予定です。残念ながら、実行可能になったスレッドを実行するための待ち時間は、2.6カーネルから3.2カーネルに大幅に増加したようです。実際、私たちが得ている待ち時間の数値は信じがたいものです。

テストについてより具体的に説明します。2つのスレッドを実行するプログラムがあります。最初のスレッドは現在の時刻(RDTSCを使用したティック単位)を取得し、1秒に1回条件変数を通知します。2番目のスレッドは、条件変数で待機し、シグナルが送られると起動します。次に、現在の時刻を取得します(RDTSCを使用したティック単位)。2番目のスレッドの時間と最初のスレッドの時間の差が計算され、コンソールに表示されます。この後、2番目のスレッドは条件変数をもう一度待機します。約2秒後、最初のスレッドによって再度シグナルが送信されます。

つまり、結果として、1秒に1回、条件変数のレイテンシ測定を介してスレッド間通信を取得します

カーネル2.6.32では、この待ち時間は2.8〜3.5 us程度であり、これは妥当です。カーネル3.2.0では、このレイテンシは40〜100 us程度に増加しています。2つのホスト間のハードウェアの違いを除外しました。それらは同一のハードウェアで動作します(ハイパースレッディング、スピードステップ、およびすべてのC状態がオフの状態で3.6 GHzで動作するデュアルソケットX5687 {Westmere-EP}プロセッサー)。テストアプリは、同じソケットの独立した物理コアで実行するようにスレッドのアフィニティを変更します(つまり、最初のスレッドはCore 0で実行され、2番目のスレッドはCore 1で実行されます)。したがって、スレッドのバウンスはありません。コアまたはソケット間のバウンス/通信。

2つのホストの唯一の違いは、1つはカーネル2.6.32-28(高速コンテキストスイッチボックス)でUbuntu 10.04 LTSを実行しており、もう1つはカーネル3.2.0-23(低速コンテキスト)で最新のUbuntu 12.04 LTSを実行していることです。スイッチボックス)。BIOS設定とハードウェアはすべて同じです。

スレッドの実行をスケジュールするのにかかる時間のこのとんでもない速度低下を説明できるカーネルの変更はありましたか?

更新: ホストとLinuxビルドでテストを実行したい場合は、閲覧用のコードをペーストビンに投稿しました。コンパイル:

g++ -O3 -o test_latency test_latency.cpp -lpthread

実行(少なくともデュアルコアボックスがあると仮定):

./test_latency 0 1 # Thread 1 on Core 0 and Thread 2 on Core 1

更新2:カーネルパラメータの検索、カーネルの変更に関する投稿、および個人的な調査の結果、問題が何であるかがわかり、この質問に対する回答として解決策を投稿しました。


1
推測だけですが、パラメータを変更すると/proc/sys/kernel/*うまくいくかもしれません。動作するものが見つかった場合は、その構成/etc/sysctl.confまたはファイルを配置し/etc/sysctl.d/て、再起動後も保持されるようにします。
CarlosCampderrós、2012

1
2つのホスト間で/ proc / sys / kernelを比較しましたが、特にスケジューリング関連の構成項目では、意味のある違いはありません。
Michael Goldshteyn

RDTSCがコア間で必ずしも適切に同期されないという噂を漠然と思い出しますが、これが問題である場合は時間の逆転が見られると思います。同じコアで両方のスレッドを実行するための親和性をいじってみて、何が起こるか見てみましたか?
デビッド・ギブン

この新しいIntelコアでは、RDTSCはコア全体、特に同じCPU(つまり同じソケット)のコア全体で問題なく動作します。興味深いことに、両方のスレッドが同じコアで実行されている場合、レイテンシは新しいカーネルで4〜10 usに減少し、約 古いカーネルでは3 us。
Michael Goldshteyn

ただの一般的なコメント-TSCの同期化への依存はせいぜい不確かですが、特定のケースでは、1つの物理チップで2つのコアを使用しているため、実際に機能するはずです。
twalberg 2012

回答:


95

最近のカーネルの悪いスレッドウェイクアップパフォーマンス問題の解決策は、古いカーネルで使用されているintel_idleからのcpuidleドライバーへの切り替えに関係してacpi_idleいます。悲しいことに、intel_idleドライバーはCステートのユーザーのBIOS設定を無視し、独自の曲に合わせて踊ります。言い換えると、PC(またはサーバー)のBIOSですべてのC状態を完全に無効にしても、このドライバーは、すべてのコアが合成ベンチマーク(たとえば、ストレス) が走っています。ほとんどの互換性のあるハードウェアで素晴らしいGoogle i7zツールを使用して、C状態遷移を、プロセッサー周波数に関連するその他の有用な情報とともに監視できます。

セットアップで現在アクティブなcpuidleドライバーを確認するには、次のセクションのでcurrent_driverファイルをcatします。cpuidle/sys/devices/system/cpu

cat /sys/devices/system/cpu/cpuidle/current_driver

最新のLinux OSで可能な限り最小のコンテキストスイッチレイテンシを実現するには、次のカーネルブートパラメーターを追加して、これらの省電力機能をすべて無効にします。

Ubuntuの12.04で、あなたはそれらを追加することによってこれを行うことができますGRUB_CMDLINE_LINUX_DEFAULTにエントリー/etc/default/grubしてから実行していますupdate-grub。追加するブートパラメータは次のとおりです。

intel_idle.max_cstate=0 processor.max_cstate=0 idle=poll

以下は、3つの起動オプションの機能に関する詳細です。

intel_idle.max_cstateゼロに設定すると、cpuidleドライバーがacpi_idle(少なくともオプションのドキュメントに従って)に戻るか、完全に無効になります。私のボックスでは完全に無効になっています(つまり、current_driverファイルを表示/sys/devices/system/cpu/cpuidleするとの出力が生成されますnone)。この場合、2番目の起動オプションprocessor.max_cstate=0は不要です。ただし、ドキュメントには、intel_idleドライバーのmax_cstateをゼロに設定すると、OSがacpi_idleドライバーに。したがって、念のため、2番目の起動オプションを設定しました。

このprocessor.max_cstateオプションは、acpi_idleドライバーの最大C状態をゼロに設定し、できればそれも無効にします。私がintel_idle.max_cstate=0使用できるすべてのハードウェアのcpuidleドライバを完全に無効にするため、これをテストできるシステムがありません。ただし、インストールで最初の起動オプションのみからintel_idleに戻ったacpi_idle場合は、2番目のオプションかどうかをお知らせください。processor.max_cstateがコメントに記載。これにより、この回答を更新できます。

最後に、3つのパラメーターの最後、 idle=poll本当のパワー豚です。これはC1 / C1Eを無効にし、レイテンシの最後の残りのビットを削除しますが、消費電力は大幅に増加します。そのため、本当に必要な場合にのみ使用してください。C1 *レイテンシはそれほど大きくないため、ほとんどの場合、これはやり過ぎです。元の質問で説明したハードウェアで実行しているテストアプリケーションを使用した場合、レイテンシは9 usから3 usになりました。これは確かにレイテンシの影響を受けやすいアプリケーション(例:金融取引、高精度テレメトリ/追跡、高頻度のデータ収集など)の大幅な削減ですが、大多数の場合、発生する電力に見合う価値はありません。デスクトップアプリ。確実に知る唯一の方法は、アプリケーションのパフォーマンスの向上と比較してプロファイルすることです。

更新:

様々で、追加のテストの後idle=*のパラメータ、私が設定することを発見したidlemwaitは、ハードウェアでサポートされている場合ははるかに良いアイデアです。の使用と思われMWAIT/MONITORた命令は、CPUが目立っレイテンシがタイムアップスレッドウェイクに追加されることなく、C1Eを入力することができます。を使用するとidle=mwait、CPU温度が(と比較してidle=poll)低くなり、電力使用量が少なくなり、ポーリングアイドルループの優れた低遅延が維持されます。したがって、これらの調査結果に基づいてCPUスレッドのウェイクアップレイテンシを低くするために更新した推奨のブートパラメーターセットは次のとおりです。

intel_idle.max_cstate=0 processor.max_cstate=0 idle=mwait

idle=mwait代わりにを使用するとidle=poll、ターボブーストの開始(CPUがTDP [熱設計パワー]を下回るのを助けること)とハイパースレッディング(MWAITが同時に物理コア全体を消費しないための理想的なメカニズム)より高いC状態を回避する時間)。これはまだテストでは証明されていませんが、私はテストを続けます。

アップデート2:

mwaitアイドルオプションがされた新しい3.xのカーネルから削除(更新用のユーザck_のおかげで)。これには、2つのオプションがあります。

idle=halt-と同様に機能するはずmwaitですが、ハードウェアに当てはまるかどうかをテストして確認してください。HLT命令はほぼ同等ですMWAIT with状態ヒント0と。問題は、HLT状態から抜け出すために割り込みが必要であるのに対し、メモリ書き込み(または割り込み)を使用してMWAIT状態から抜け出すことができるという事実にあります。Linuxカーネルがアイドルループで何を使用するかに応じて、これによりMWAITが潜在的に効率的になる可能性があります。だから、私がテスト/プロファイルを言って、それがあなたの待ち時間のニーズを満たしているかどうかを見てください...

そして

idle=poll -電力と熱を犠牲にして、最高のパフォーマンスオプション。


申し訳ありませんが、C状態がファームウェアによって管理されることを期待していたのはなぜですか?一時停止状態はランタイム状態であり、OSによって意図的に管理されます。気付いたように、ランタイムサスペンドが必要ない場合は、使用しないでください。
アンディロス

6
申し訳ありませんが、Cでは、EISTとC1EはBIOSでオフにできると述べています。OSがBIOS設定を尊重することを期待しています。この場合の恐ろしいツールとドキュメントを考えると、これは特に当てはまります。
Michael Goldshteyn 2012

4
おそらく、あなたの経歴を介してオフになっています。それを必要とする関連仕様には何も知りません。申し訳ありませんが、「期待」 BIOSから繰り返しあなたを噛まないように起こっています。ファームウェアが最新のPCで実行できる最善のことは何もありません。驚いて申し訳ありませんが、率直に言ってこれはユーザーのエラーです。ベンチマークは、中断時間と再開時間を測定していました。
アンディロス

19
BIOS機能選択の役割の1つは、デバイスを有効/無効にすることです。場合によっては、これらの選択はOSで強制されます(たとえば、マザーボード上のUSB、eSATA、およびNIC)。他のものでは、OSはあなたの希望を尊重することが期待されています(たとえば、EIST、C状態、ハイパースレッディング、実行の無効化、AES-NI、仮想化など)。BIOSは、OSに中立な単一の中央デバイス/機能選択面を提供します。これにより、ユーザーは、同じハードウェア機能を使用する複数の(おそらく大きく異なる)OSをホストにインストールできます。ただし、この回答は主観的なものであるため、同意しないことに同意する必要があります。
Michael Goldshteyn 2012

1
idle = mwaitは最近の3.xカーネルでサポートされなくなりましたlkml.org/lkml/2013/2/10/21代替アドバイスはありますか?
ck_ 14

8

おそらく、遅くなったのは条件変数の構成要素であるfutexです。これはいくつかの光を放つでしょう:

strace -r ./test_latency 0 1 &> test_latency_strace & sleep 8 && killall test_latency

その後

for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done

これは、興味深いシステムコールにかかったマイクロ秒を時間でソートして表示します。

カーネル2.6.32

$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
 1.000140 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000129 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000124 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000119 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000106 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000103 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000102 futex(0x601ac4, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601ac0, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 0.000125 futex(0x7f98ce4c0b88, FUTEX_WAKE_PRIVATE, 2147483647) = 0
 0.000042 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000038 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000037 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000030 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000029 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 0
 0.000028 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000027 futex(0x601b00, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000018 futex(0x7fff82f0ec3c, FUTEX_WAKE_PRIVATE, 1) = 0
nanosleep
 0.000027 nanosleep({1, 0}, {1, 0}) = 0
 0.000019 nanosleep({1, 0}, {1, 0}) = 0
 0.000019 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, {1, 0}) = 0
 0.000018 nanosleep({1, 0}, 0x7fff82f0eb40) = ? ERESTART_RESTARTBLOCK (To be restarted)
 0.000017 nanosleep({1, 0}, {1, 0}) = 0
rt_sig
 0.000045 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000040 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000038 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000034 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000033 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000032 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000032 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000028 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000028 rt_sigaction(SIGRT_1, {0x37f8c052b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
 0.000027 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000027 rt_sigaction(SIGRTMIN, {0x37f8c05370, [], SA_RESTORER|SA_SIGINFO, 0x37f8c0e4c0}, NULL, 8) = 0
 0.000027 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000023 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000022 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
 0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000021 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000019 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0

カーネル3.1.9の場合

$ for i in futex nanosleep rt_sig;do echo $i;grep $i test_latency_strace | sort -rn;done
futex
 1.000129 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000126 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000122 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000115 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000114 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000112 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 1.000109 futex(0x601764, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x601760, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
 0.000139 futex(0x3f8b8f2fb0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
 0.000043 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000041 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000037 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000036 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
 0.000034 futex(0x601720, FUTEX_WAKE_PRIVATE, 1) = 1
nanosleep
 0.000025 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000022 nanosleep({1, 0}, {0, 3925413}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
 0.000021 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
 0.000017 nanosleep({1, 0}, 0x7fff70091d00) = 0
rt_sig
 0.000045 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000044 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000043 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000040 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000038 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000037 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000036 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000035 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000034 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000031 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000027 rt_sigaction(SIGRT_1, {0x3f892067b0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0
 0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000026 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000025 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000024 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
 0.000023 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
 0.000022 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
 0.000021 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
 0.000019 rt_sigaction(SIGRTMIN, {0x3f89206720, [], SA_RESTORER|SA_SIGINFO, 0x3f8920f500}, NULL, 8) = 0

比較する「ピンポン」パフォーマンステストを含むこの5年前のバグレポートを見つけました

  1. シングルスレッドlibpthreadミューテックス
  2. libpthread条件変数
  3. プレーンな古いUnixシグナル

追加しなければならなかった

#include <stdint.h>

コンパイルするために、私はこのコマンドでやった

g++ -O3 -o condvar-perf condvar-perf.cpp -lpthread -lrt

カーネル2.6.32

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29085 us; per iteration:   29 ns / 9.4e-05 context switches.
c.v. ping-pong test   elapsed:  4771993 us; per iteration: 4771 ns / 4.03 context switches.
signal ping-pong test elapsed:  8685423 us; per iteration: 8685 ns / 4.05 context switches.

カーネル3.1.9の場合

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    26811 us; per iteration:   26 ns / 8e-06 context switches.
c.v. ping-pong test   elapsed: 10930794 us; per iteration: 10930 ns / 4.01 context switches.
signal ping-pong test elapsed: 10949670 us; per iteration: 10949 ns / 4.01 context switches.

カーネル2.6.32と3.1.9の間のコンテキスト切り替えは、カーネル3.2で観察したほどではありませんが、実際には遅くなっていると私は結論付けます。これはまだあなたの質問に答えていないことに気づきました。掘り続けます。

編集:プロセス(両方のスレッド)のリアルタイムの優先順位を変更すると、2.6.32と一致するように3.1.9のパフォーマンスが向上することがわかりました。ただし、2.6.32で同じ優先順位を設定すると、速度が低下します...数値を計算してください。詳しく調べます。

これが私の結果です:

カーネル2.6.32

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29629 us; per iteration:   29 ns / 0.000418 context switches.
c.v. ping-pong test   elapsed:  6225637 us; per iteration: 6225 ns / 4.1 context switches.
signal ping-pong test elapsed:  5602248 us; per iteration: 5602 ns / 4.09 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex                 elapsed:    29049 us; per iteration:   29 ns / 0.000407 context switches.
c.v. ping-pong test   elapsed: 16131360 us; per iteration: 16131 ns / 4.29 context switches.
signal ping-pong test elapsed: 11817819 us; per iteration: 11817 ns / 4.16 context switches.
$ 

カーネル3.1.9の場合

$ ./condvar-perf 1000000
NPTL
mutex                 elapsed:    26830 us; per iteration:   26 ns / 5.7e-05 context switches.
c.v. ping-pong test   elapsed: 12812788 us; per iteration: 12812 ns / 4.01 context switches.
signal ping-pong test elapsed: 13126865 us; per iteration: 13126 ns / 4.01 context switches.
$ chrt -f 1 ./condvar-perf 1000000
NPTL
mutex                 elapsed:    27025 us; per iteration:   27 ns / 3.7e-05 context switches.
c.v. ping-pong test   elapsed:  5099885 us; per iteration: 5099 ns / 4 context switches.
signal ping-pong test elapsed:  5508227 us; per iteration: 5508 ns / 4 context switches.
$ 

FedoraとCentOSで実行しましたが、Ubuntuはありません。結果を投稿します。
amdn

OK、私は両方のホスト(つまり、異なるカーネル)で実行しましたが、結果にはほとんど差異がありません。そのため、このテストでは違いは強調されませんでした。futexの呼び出し時間は小数点第4位で異なります-パフォーマンスのわずかな低下。エラー待って、整数は秒単位ですか?私はあなたがあなたの結果を投稿したのを見ました、そしてそれらは私のものに似ているように見えます...
Michael Goldshteyn

これでfutexの実装が除外されました-コンテキストスイッチの理論に戻ります...この回答はコメントに属しているので、自由に削除してください...コマンドをフォーマットする機能が必要でした。
amdn

はい、時間は秒単位です... 1秒以上続くfutexの呼び出しは、条件で待機しているスレッドに対するものです。
amdn

それで、もし結果から何か得たらどうしますか?
Michael Goldshteyn 2012

1

また、c-stateとは別のpstateドライバーが原因で、最近のプロセスやLinuxカーネルでプロセッサーがクリックダウンするのを見ることもあります。したがって、これを無効にするには、次のカーネルパラメータを使用します。

intel_pstate=disable

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.