3

ここには、C++ と FORTRAN が混在する非常に大きなプログラムがあります (申し訳ありません)。私のチェックインの 1 つは、私の変更の影響を受けないコードの領域でさえ、アプリケーション全体の劇的な速度低下 (つまり、2 倍以上) をもたらしました。

事実:

  1. 私のコードをまったく使用していないモジュールも含め、ほぼすべてのモジュールが同程度に遅くなりました。

  2. 実行可能ファイルは約 6% 大きくなります。

  3. メタデータはチェックイン間で変更されていません。

  4. IDE/コンパイラは、リリース モードの VS2010 です。

  5. 一部の .lib ファイルのサイズは 2 倍または 3 倍になりました。

サイズが 3 倍になった .lib ファイルの 1 つを確認しましたが、変更点は 2 つだけです。

a) 大きなヘッダー ファイルをインクルードしました。このファイルには、他の多くのファイルが含まれています。その中には、適度に複雑なインライン コードが含まれているものもあります。「追加のインクルード ディレクトリ」は、各ヘッダー ファイルが 1 つまたは複数の他のファイルを #include するため、0 または 1 から約 7 になりました。

b) このヘッダー ファイルから 4 つの関数を呼び出しましたが、速度が低下した実行中には呼び出されませんでした (つまり、それらの実行によってコードの速度が低下することはありませんが、それらを含めると速度が低下する可能性があります)。

ヘッダー ファイルを含めると (コンパイルではなく)実行が遅くなるかどうかについてフォーラムを検索しても、関連する記事が 1 つも見つかりません。私の質問は次のとおりです。

? 任意の形式のヘッダー (宣言またはインライン) を#include すると、コードの実行が遅くなりますか?

? 実行速度に関してインラインコードを含めることには、質的または量的な違いがありますか(「インライン」はコンパイラへのアドバイスにすぎないことを知っています)?

? .lib のサイズ、.exe のサイズ、および実行速度の相関関係は何ですか?

? (これらのインクルードを .cpp ファイルに入れ、「追加のインクルード ディレクトリ」を減らすことによって) 他のものをインクルードする必要がないように、一部のヘッダー ファイルをリファクタリングすると、状況が改善されると思いますか?

最後の質問は、かなりの労力がかかるため、問題の核心だと思います...

4

6 に答える 6

5

#include 形式のヘッダー (宣言またはインライン) を使用すると、コードの実行が遅くなりますか?

未使用の宣言を追加したり、未使用のインライン定義を追加したりしても、実行は遅くなりません。ただし、実行を遅くする可能性のあるいくつかのことを想像できます。

  • 一部の #define は、一般的に使用される関数の最適化されたインラインまたはマクロ バリアントが、さらに下の別のヘッダーによって提供されるのを防ぎます。
  • おそらく標準ライブラリ内から、一般的に使用されるいくつかの操作のオーバーロードであり、デフォルトよりも効率的ではありません。

実行速度に関してインラインコードを含めることには、質的または量的な違いがありますか(「インライン」はコンパイラへのアドバイスにすぎないことを知っています)?

コードが利用できない場合は、インライン化できません。もしそうなら、それはできます。通常、コンパイラは、インライン化によって節約される量を見積もることができますが、それが役に立たない場合はインライン化しませんが、場合によっては間違った推測をすることがあります。そのような場合、結果はわずかに役立つ通常のケースとは大きく異なります。

.lib のサイズ、.exe のサイズ、および実行速度の相関関係は何ですか?

ケースバイケースで全然違う。インライン化するとコード サイズが大きくなりますが、各呼び出しサイトで多くの作業を節約できます。ただし、コードが大きくなるとキャッシュが多くなり、速度が低下します。

(これらのインクルードを .cpp ファイルに入れ、「追加のインクルード ディレクトリ」を減らすことによって) 他のものをインクルードする必要がないように、一部のヘッダー ファイルをリファクタリングすると、状況が改善されると思いますか?

そうかもしれないし、そうでないかもしれない。実際の原因によります。

その原因を徹底的に探ったほうがいいと思います。含まれるコードの量ではなく、特定のコードが原因であることがほぼ確実です。そこで、変更前のリビジョンに戻って、含まれているものを少しずつ追加します。最初に最も内側のヘッダーだけをインクルードし、それらを使用するヘッダーを 1 つずつ追加します。事態を悪化させる特定のヘッダーに到達したら、特定の宣言またはそれらのいくつかに絞り込むまで、その一部をコメントアウトしてみてください。

また、パフォーマンスの低下が見られる関数だけを取り出します。絞り込んでも何が問題なのかがわからない場合は、他の人が問題を再現できるものがあるため、新しい質問として使用できます。

于 2012-10-03T13:59:22.783 に答える
1

ヘッダーファイルを変更しても、DEBUGまたはその他の診断コードを結果のバイナリに組み込むものを誤ってインクルードしない限り、実行時間を変更することはできません。

それは私の推測です。出力ファイルサイズの変更を前提としています。

于 2012-10-03T13:29:34.593 に答える
1

COMを使用していますか?インクルード ファイルによって STA が MTA に変更されましたか、またはその逆でしたか? インクルード ファイルは、ダイナミック リンク (lib プラグマ) を使用する前のライブラリをプルしますか? インクルードはライブラリを取り込まなくなり、コードは動的にリンクしなくなりましたか? スティーブと繰り返しますが、デバッグ ライブラリは含まれていますか?

DUMPBIN は、実際に構築されたものに関する追加の洞察を提供する場合があります。結果を古いバージョンと比較して、何か大きな点が際立っているかどうかを確認します。

追加の編集: テスト マシンのメモリ使用量をチェックし、ページング アクティビティをチェックして、より大きな exe がしきい値を超えた可能性をなくします。

于 2012-10-03T13:42:39.970 に答える
1

1 ブラインド ショット :

キャッシュの問題である可能性があります。関数をインライン化し、「デッド」コードをライブラリに追加すると、コードが大きくなり、プログラムの実行中にキャッシュ ミスの量が増える可能性があります。

プロセスの実行中にキャッシュ ミスの数を監視するだけで、これが正しいパスであるかどうかを確認できます。


あなたのコメントについて:

6% はいくらですか?

L1 キャッシュがオーバーフローした場合 (私の知る限り、そのサイズは最新のプロセッサでも約 32K です)、L1 アクセスを L2 アクセスと交換しますが、これは最大 2 倍遅くなります。L2 キャッシュ (256K から 2M の範囲) をオーバーフローさせて L3 へのアクセスを開始すると、ページのフェッチがさらに 5 倍遅くなります (コア i7 の数値を示すこの質問を確認できます)。

ウィキペディアのキャッシュ ミスに関する一般的な説明を次に示します。

繰り返しますが、これが本当に問題であるかどうかを確認するには、プロセスの実行中にヒットしたキャッシュ ミスの数を監視する必要があります ( Windows を使用している場合はプロセス エクスプローラー、 Linux を使用している場合はperfでこれが表示されると思います)。

于 2012-10-03T14:19:52.013 に答える
0
  • #include 形式のヘッダー (宣言またはインライン) を使用すると、コードの実行が遅くなりますか? まあ、あなたのアプリがしなければならないなら

    それはコードが現れる場所を変えるだけなので、何も変わらないと思います。(関数を 3 行上に移動するだけでは、コードは速くも遅くもなりませんよね?)

  • 実行速度に関してインラインコードを含めることには、質的または量的な違いがありますか(「インライン」はコンパイラへのアドバイスにすぎないことを知っています)

    多分。インライン関数と非インライン関数を比較すると、インライン関数はコードが適切な場所にコピーペーストされるだけなので、インライン関数の方が高速である可能性がありますが、通常の関数は関数呼び出しに時間を浪費します。

  • .lib サイズ、.exe サイズ、および実行速度の相関関係は何ですか (ここでは、多くの異なる相反する相関関係が予想されます)。

    ファイルが大きくなると速度が低下するという仮説的な状況を想像することはできますが、ほとんどの場合、相関関係はないと言っていいでしょう。

実行に影響を与えるいくつかのマクロをオーバーライドした可能性があるため、実行可能ファイルはおそらく大きくなります (一部のコードを除外することを意図した定義を未定義にするなど)。これは、パフォーマンスの低下にもつながる可能性があります (つまり、一部のコードを実行したくありませんでしたが、誤ってマクロを再定義したためです)。

于 2012-10-03T13:36:28.883 に答える
0

当て推量で問題が見つかる可能性は低いです。診断はそれを見つけるでしょう。速度低下が 2 倍の場合、速度の遅いコードは時間の 50% を、以前は実行していなかった不要な処理に費やしていることを意味します。これは非常に見つけやすいでしょう。

これは問題を見つけるため、私が使用する方法です。 ここに例を示します。これにはいくつかの理由があります。

最初に最適化されていないコードの問題を診断することをお勧めします。次に、問題を一掃したら、オプティマイザーをオンにして、それを実行させます。コードには、ユーザーが修正でき、オプティマイザーでは修正できない重大な問題が含まれている可能性が非常に高くなります。オプティマイザーが何をしても、自分だけが修正できる問題を簡単に見つけることはできません。

于 2012-10-03T18:08:39.657 に答える