7

C++ プログラムのパフォーマンスを最適化し、実行時間を短縮しようとしています。ただし、ボトルネックがどこにあるかを理解するのに苦労しています。

time コマンドは、プログラム自体の実行に約 5 分かかり、約 5 分、ユーザーの CPU 時間は 4.5 分かかることを示しています。

CPU プロファイラー (gcc プロファイラーと google perftool の両方) は、関数呼び出しの CPU 時間は合計で 60 秒しかかからないことを示しています。また、プロファイラーを使用して、CPU 時間ではなくリアルタイムでサンプリングしようとしましたが、同様の結果が得られました。

I/O プロファイラー (私は ioapps を使用しました) も、I/O がプログラムの実行時間の約 30 秒しかかからないことを示しています。

したがって、基本的には 3.5 分 (プログラム実行時間の最大部分) が考慮されておらず、そこがボトルネックであると考えています。

何を見逃したのか、その時間がどこに行くのかを知るにはどうすればよいですか?

4

1 に答える 1

7

Öö Tiib が示唆したように、デバッガーでプログラムを中断するだけです。私がそれを行う方法は、プログラムを実行し、出力ウィンドウに切り替え、Ctrl-C を入力してプログラムを中断し、GDB ウィンドウに戻り、「スレッド 1」と入力してメイン プログラムのコンテキストになるようにすることです。 「bt」と入力して、スタック トレースを表示します。

ここで、スタック トレースを見て理解します。これは、プログラム カウンターの命令が特定のサイクルの消費に関与しているのに対し、スタック上のすべての呼び出しも同様であるためです

これを数回行うと、ボトルネックの原因となっている行が正確にわかります。2 つのサンプルでそれを見るとすぐに、あなたはそれを釘付けにしています。次に、それを修正してすべてやり直して、次のボトルネックを見つけます。この方法で大幅な高速化が得られることが簡単にわかります。

<炎>

これはまさにプロファイラーが行うことだと言う人もいますが、プロファイラーの方が優れているだけです。これは講堂やブログで耳にすることですが、取り決めは次のとおりです。「遅い関数」や「ホット パス」として明らかにならないコードを高速化する方法があります。たとえば、データ構造を再編成します。包含時間の割合が高い場合でも、すべての関数は多かれ少なかれ無害に見えます。

スタックサンプルを実際に見ると、それらは明らかになります。したがって、優れたプロファイラーの問題は、サンプルの収集ではなく、結果の表示にあります。統計と測定では、慎重に調べた少数のサンプルから何がわかるかを知ることはできません。

少数のサンプルと多数のサンプルの問題についてはどうですか? もっと良くないですか?OK、無限ループがあるとしますか、それとも無限でなくても、予想よりもはるかに長く実行されますか? 1000 スタックのサンプルは、単一のサンプルよりも優れていると思いますか? (いいえ。) デバッガーで見ると、基本的に 100% の時間がかかるため、ループに陥っていることがわかります。スタックのどこかにあります - 見つかるまでスタックをスキャンしてください。ループが 50% または 20% の時間しかかからないとしても、それは各サンプルがそれを見る確率です。したがって、わずか 2 つのサンプルで取り除くことができるものを見つけた場合は、それを実行する価値があります。では、1000 個のサンプルで何が得られるのでしょうか?

「では、問題を 1 つか 2 つ見落としたらどうしよう。もしかしたらそれで十分かもしれない」と考える人もいるかもしれません。そうですね?コードに 3 つの問題があり、P が 50%、Q が 25%、R が 12.5% かかるとします。良いものは A と呼ばれます。これは、そのうちの 1 つ、2 つ、または 3 つすべてを修正した場合に得られる速度向上を示しています。

PRPQPQPAPQPAPRPQ original time with avoidable code P, Q, and R all mixed together
RQQAQARQ         fix P           - 2 x   speedup
PRPPPAPPAPRP     fix Q           - 1.3 x    "
PPQPQPAPQPAPPQ   fix R           - 1.14 x   "
RAAR             fix P and Q     - 4 x      "
QQAQAQ           fix P and R     - 2.7 x    "
PPPPAPPAPP       fix Q and R     - 1.6 x    "
AA               fix P, Q, and R - 8 x   speedup

これは、「逃げる」人が本当に傷つく理由を明確にしていますか? 見逃した場合にできる最善のことは、2倍遅くすることです。

サンプルを調べれば簡単に見つけることができます。P はサンプルの半分にあります。P を修正してもう一度行うと、Q はサンプルの半分になります。Q を修正すると、R はサンプルの半分になります。R を修正すると、8 倍のスピードアップが得られます。そこで止まる必要はありません。本当に修正するものが見つからなくなるまで、続けることができます。

問題が多ければ多いほど、高速化の可能性は高くなりますが、見逃すわけにはいきません。プロファイラー (優れたプロファイラーであっても) の問題は、個々のサンプルを表示して調査する機会を奪うことで、見つけなければならない問題を隠してしまうことです。 そのすべてについてもっと。 統計に傾倒している方のために、これがどのように機能するかを示します。

優れたプロファイラーがあります。最高のものは、ホットキーでサンプリングのオンとオフを切り替えることができる、個々の行で包括的パーセントを報告するウォールタイム スタック サンプラーです。 Zoom ( wiki ) はそのようなプロファイラーです。

しかし、それらでさえ、大量のサンプルが必要であると想定するという間違いを犯しています。あなたはそうしません、そしてあなたが支払う代償はあなたが実際に何も見ることができないということです.なぜ時間が費やされているのか分かりません.必要ないとわかっていない限り、何かを取り除きます。その結果、ボトルネックを見逃すことになり、スピードアップが妨げられてしまいます。

< /炎>

于 2013-08-13T19:32:40.763 に答える