12

やや大きなマシン (32 コア、256 GB RAM) で作成したマルチスレッド プログラムのプロファイルを作成しようとしています。実行ごとに、プログラムのパフォーマンスが大幅に (70 ~ 80%) 変わる可能性があることに気付きました。プログラムのパフォーマンスにおけるこの巨大な差異の原因を見つけることはできないようですが、多数の実行で「時間」ユーティリティの結果を分析することによって、非自発的なコンテキスト スイッチの数が、プログラムのパフォーマンス (明らかに、コンテキスト スイッチが少ないほどパフォーマンスが向上し、その逆も同様です)。

このコンテキスト切り替えの原因を特定する良い方法はありますか? 犯人を発見できれば、問題を解決できるかもしれません。ただし、使用できるツールにはいくつかの特定の制限があります。まず、マシンのルート権限を持っていないため、そのような権限を必要とするツールはありません。第 2 に、これはかなり古いカーネル (RHEL5、カーネル 2.6.18) であるため、標準的な perf-event の一部が存在しない可能性があります。とにかく、このコンテキスト切り替えの原因をより深く掘り下げる方法についての提案は大歓迎です。

アップデート:私は自分のプログラムを別の (そして小さい) マシンでテストすることにしました。もう一方のマシンは、8Gb の RAM を搭載した 4 コア (ハイパースヘディング付き) の Linux ボックスで、カーネルははるかに新しいものです --- 他のマシンでは 3.2.0 対 2.6.18 です。新しいマシンでは、バイモーダル パフォーマンス プロファイルを再現できません。これは、問題がハードウェアの問題 (コメントで示唆されているように) によるものか、カーネルレベルでの特に病理学的なケースが原因であり、その後修正されたものであると私に信じさせます。私の現在の最良の仮説は、新しいマシンには完全に公平なスケジューラ (CFS) を備えたカーネルがあり、古いマシンには含まれていないという事実の結果である可能性があるというものです。新しいマシン用に古いカーネル バージョンを再コンパイルすることなく、この仮説をテストする (新しいマシンに別の/古いスケジューラを使用するように指示する) 方法はありますか?

4

6 に答える 6

8

コアが 32 個あるとおっしゃいましたが、ハードウェアの正確なレイアウトはどのようなものですか? たとえば、マシンに含まれるパッケージの数、コアの数、キャッシュの共有方法などです。この種の情報を共有するために、私は個人的に の出力を共有するのが好きですlikwid-topology -g

とにかく、実行には非決定論が 1 つあります。それは、スレッド アフィニティです。オペレーティング システムは、スレッドがどのように通信するかについての知識を考慮せずに、SW スレッドを特定の HW スレッドで実行するように割り当てます (その知識がないため)。これはあらゆる種類の影響を引き起こす可能性があるため、再現可能な実行のために、何らかの方法で SW スレッドを HW スレッドに確実に固定することをお勧めします (最適な方法もあるかもしれませんが、ここまでは決定論について話しているだけです)。

ピニング (別名アフィニティ) には、明示的な Pthread 呼び出しを使用するか、Likwid スイートの別のツールを試すことができますlikwid-pin-こちらを参照してください。

それでも一貫した結果が得られない場合は、ワークロードで適切なプロファイラー (Intel VTune など) を実行して、高速の実行と低速の実行をキャプチャし、結果を比較してください。VTune では、2 つのプロファイルを並べて表示する比較機能を使用できます。

于 2013-07-02T04:44:33.837 に答える
1

あるマシンでは見られ、他のマシンでは見られないバイモーダル パフォーマンス プロファイルについて言及しています。これは恐ろしいことですが、シングル スレッド アプリケーションであっても、これは正常な動作です。

問題は、アプリケーションのパフォーマンスに影響を与える Linux システム (使用するスケジューラに関係なく、任意のカーネル) に非常に多くの要因があることです。それはアドレスのランダム化から始まり、微視的なタイミングの違いで終わり、プロセス間の巨大なコンテキスト スイッチの遅延にまでエスカレートします。

Linux はリアルタイム システムではありません。平均的なケースで可能な限り効率的になろうとするだけです。

パフォーマンスの差異を最小限に抑えるためにできることはいくつかあります。

スレッドの数を必要最小限に減らします。問題のさまざまな側面をスレッドに分割しないでください。本当に必要な場合は、スレッドに分割してください。たとえば、独立した (!) 数値処理ジョブを CPU に供給する場合などです。できるだけ多くの因果関係のある作業を 1 つのスレッドで行うようにしてください。スレッドは、相互の通信をできるだけ少なくする必要があります。特に、レイテンシが加算されるスレッド間にリクエスト/レスポンス パターンを持たないようにする必要があります。

OS がスレッド/プロセス間で 1 秒あたり約 1000 のコンテキスト スイッチしか実行できないと仮定します。これは、1 秒あたり数 100 の要求/応答トランザクションを意味します。Linux でベンチマークを実行して、もっと多くのことができることがわかった場合は、これを無視してください。

重要なデータのメモリ フットプリントを減らすようにしてください。分散データはキャッシュを破壊する傾向があり、パフォーマンスへの影響は非常に微妙で説明が困難です。

于 2013-07-01T19:54:23.577 に答える
0

マルチスレッド プログラムで、特定の CPU 番号にスレッドを接続し、パフォーマンスが向上するかどうかを確認します。

于 2013-07-02T05:26:34.850 に答える
0

再スケジュールに関しては、カーネル プロファイラー/ロガーFtraceを使用するのが最善の策です。これにより、どのスレッドが他のスレッドによってプリエンプトされているかがわかります。残念ながら、下半分の割り込みハンドラは適切にラベル付けされていないため、これらを解読するのは困難です。

于 2013-07-02T09:18:31.103 に答える