次の方法で共有


適切に動作しないマルチスレッド アプリケーションの一般的なパターン

同時実行ビジュアライザーは、マルチスレッド アプリケーションの動作を視覚化するのに役立ちます。このツールには、適切に動作しないマルチスレッド アプリケーションの一般的なパターンのギャラリーがあります。ギャラリーには、このツールで公開される一般的で認識可能なパターン、各パターンが表す動作の説明、その動作によって引き起こされる可能性が高い結果、およびその問題の最も一般的な解決方法が含まれています。

ロックの競合およびシリアル化された実行

シリアル化実行でのロック競合の結果

並行処理されるアプリケーションが、複数のスレッドがあり、コンピューターに十分な論理コアがあるにもかかわらず、シリアル実行を続行する場合があります。この場合、最初に現れる現象は、シリアル アプリケーションの場合よりも処理が多少遅くなるような、マルチスレッドのパフォーマンスの低下です。スレッド ビューでは、複数のスレッドが並行実行されておらず、どの時点においても実行されているのは 1 つのスレッドだけであることが示されます。ここで、1 つのスレッド内の 1 つの同期セグメントをクリックすると、ブロックされたスレッドの呼び出し履歴 (ブロック呼び出し履歴) とブロック状態が解除されたスレッドの呼び出し履歴 (ブロック解除呼び出し履歴) が表示されます。また、分析しているプロセスでブロック解除呼び出し履歴が発生した場合は、スレッド準備完了コネクタが表示されます。ここで、ブロック呼び出し履歴とブロック解除呼び出し履歴からコードに移動して、シリアル実行が行われている原因をさらに調査することができます。

次の図に示すように、同時実行ビジュアライザーでは、複数のスレッドが存在するにもかかわらず 1 つの論理コアだけがアプリケーションで使用されている現象を、[CPU 使用状況] ビューに公開することもできます。

詳細については、MSDN ブログ Web サイトの Hazim Shafi のブログ「Parallel Performance Tools For Windows (Windows 用の並行実行ツール)」の「Performance Pattern 1: Identifying Lock Contention (パフォーマンス パターン 1: ロック競合の識別)」を参照してください。

ロック競合

不均等な作業負荷の配分

不均一なワークロード

アプリケーションの複数の並行スレッドで不規則な作業負荷が生じた場合、各スレッドがその作業を完了すると、前の図に示すように典型的なステアステップ パターンが表示されます。同時実行ビジュアライザーでは、ほとんどの場合、それぞれの同時実行スレッドについて、非常に近い開始時刻が表示されます。しかし、これらのスレッドは、同時に終了するのではなく、不規則な方法で終了するのが一般的です。このパターンは、並行スレッドのグループ内で作業負荷が不規則になっていることを示します。これは、パフォーマンスの低下につながります。このような問題を解決する最善の方法は、並行スレッド間で作業負荷が分けられるアルゴリズムを再評価することです。

次の図に示すように、同時実行ビジュアライザーでは、CPU 使用率の緩やかな低下として、この現象を [CPU 使用状況] ビューに公開することもできます。

不均一なワークロード

オーバーサブスクリプション

オーバーサブスクリプション

オーバーサブスクリプションの場合、1 つのプロセスのアクティブなスレッドの数が、システム上で使用可能な論理コアの数を上回ります。前の図は、すべてのアクティブなスレッドで大きなプリエンプション バンドがある、オーバーサブスクリプションの結果を示しています。また、凡例には、プリエンプションで経過した時間が高い割合であることが示されます。この例では、経過時間の割合が 84% になります。これは、論理コアの数を上回る並行スレッドを実行するように、プロセスがシステムに要求していることを示している可能性があります。ただし、このプロセスで使用できると想定されたリソースを、システム上の他のプロセスが使用している可能性もあります。

この問題を評価する際には、次の点を考慮する必要があります。

  • システム全体がオーバーサブスクリプションの状態である可能性があります。システム上の他のプロセスがスレッドを先取りしている可能性があることを考慮してください。スレッド ビューでプリエンプション セグメントの上にマウスを置くと、そのスレッドと、そのスレッドを先取りしたプロセスを識別するツールヒントが表示されます。このプロセスが、自分のプロセスが先取りされた時間中に実行されていたプロセスであるとは限りませんが、自分のプロセスに対する先取りのプレッシャーの原因についてのヒントになります。

  • 自分のプロセスが作業フェーズ中に実行するのに適したスレッド数を判断する方法を評価します。そのプロセスがアクティブな並行スレッドの数を直接計算する場合は、システム上で使用可能な論理コアの数により適合するように、そのアルゴリズムを変更することを検討してください。同時実行ランタイム、タスク並列ライブラリ、または PLINQ を使用する場合、これらライブラリがスレッド数を計算します。

非効率的な I/O

非効率的な I/O

I/O の過剰使用や誤使用は、アプリケーションの非効率性の一般的な原因となります。前の図に示される内容を検討してください。表示されているタイムライン プロファイルには、表示されているスレッド時間の 42% が I/O で消費されていることが示されています。このタイムラインには大量の I/O が示されています。これは、プロファイルされたアプリケーションが I/O によって頻繁にブロックされていることを意味します。I/O の種類の詳細や、どこでプログラムがブロックされているのかを確認するには、問題が発生している領域を拡大し、表示されているタイムライン プロファイルを調べてから、特定の I/O ブロックをクリックして現在の呼び出し履歴を表示します。

ロック コンボイ

ロック コンボイ

アプリケーションが先入れ先出しの順序でロックを要求し、ロックでの到着率が取得率を上回った場合に、ロック コンボイが発生します。この 2 つの状況が揃ったときに、ロック要求がバックアップを開始します。この問題を解決する方法の 1 つは、最初のスレッドにアクセスを許可して、ロック解除状態でそれらを見つけるという、"不公平な" ロックを使用することです。前の図は、このコンボイ動作を示しています。問題を解決するためには、同期オブジェクトの競合の削減と、不公平なロックの使用を試みてください。

参照

概念

スレッド ビュー (並行処理のパフォーマンス)