2

コードサイズやCPUキャッシュなどの理由で、「大きな関数は実行時間が長くなる可能性がある」とどこかで聞いたのを覚えています。

関数のサイズがアプリケーションのパフォーマンスに影響を与えているかどうかを確認するにはどうすればよいですか? これに対してどのように最適化できますか? 分割した CPU 集中型の計算があります (CPU コアと同じ数のスレッド)。メイン スレッドは、すべてのワーカー スレッドが終了するまで待機してから続行します。

私はたまたま Visual Studio 2010 で C++ を使用していますが、それが本当に重要かどうかはわかりません。

編集:

ピクセルあたり約 5,000 の光線を発射するレイ トレーサーを実行しています。(cores-1) 個のスレッド (余分なコアごとに 1 個) を作成し、画面を行に分割して、各行を CPU スレッドに割り当てます。trace各スレッドで関数を 1 ピクセルあたり約 5,000 回実行します。

私は実際にこれをスピードアップする方法を探しています。 リファクタリングによってメインのトレース関数のサイズを縮小することは可能ですが、パフォーマンスの向上が期待できるかどうかを知りたいです。

多くの人がここで間違った質問に答えているようです.私はこの特定の質問に対する答えを探しています.機能サイズ/パフォーマンスの関係。

4

4 に答える 4

5

実際には関数のサイズではなく、実行時にキャッシュされるコードの合計サイズです。コードをより多くの小さな関数に分割しても、それらの関数の一部がクリティカル コード パスでまったく呼び出されず、したがってキャッシュを占有する必要がない場合を除いて、高速化することはできません。さらに、コードを複数の関数に分割しようとすると、コンパイラがそれらをインライン化することを決定した場合、コンパイラによって元に戻される可能性があります。

したがって、現在のコードが「パフォーマンスに影響を与えている」かどうかを判断することは実際には不可能です。コードを別の方法で構造化できた多くの方法のどれと比較してヒットしましたか? そして、そのような変更がパフォーマンスに特定の違いをもたらすと合理的に期待することはできません.

あなたが探しているのは、めったに実行されない命令 (プロファイラーがどれかを教えてくれます) であると思いますが、頻繁に実行される命令のすぐ近くにあります (したがって、キャッシュにある必要があります)多く、それらの周りのキャッシュラインを引き込みます)。よく実行されるコードをまとめてクラスター化できれば、命令キャッシュをさらに活用できます。

ただし、実際には、これはあまり実りの多い最適化の行ではありません。あなたが大きな違いを生む可能性は低いです。他に何もないとしても、一般的に実行されるコードはおそらく非常に小さく、すでに隣接しています。それは、どこかで少数のタイトなループになります (プロファイラーが場所を教えてくれます)。また、最下位レベルのキャッシュ ラインは通常小さい (32 バイトまたは 64 バイト程度) ため、コードを非常に細かく再配置する必要があります。C++ では、ユーザーとオブジェクト コードとの間に多くの隔たりがあり、メモリ内で命令を慎重に配置することが妨げられています。

のようなツールperfは、キャッシュ ミスに関する情報を提供します。それらのほとんどは実行可能コードに関するものではありませんが、ほとんどのシステムでは、回避しているキャッシュ ミスは問題ではありません。コードアップします。多くのミスがない限り、おそらく多くはありませんが、いくつかあります。

とにかく、これはどのような文脈で聞いたのですか?私が聞いた中で最も一般的なのは、関数のインライン化が非生産的であるという考えです。これは、コードの肥大化によるオーバーヘッドが、回避された関数呼び出しのオーバーヘッドよりも大きい場合があるためです。よくわかりませんが、コンパイラがサポートしている場合は、プロファイルに基づく最適化が役立つかもしれません。かなり妥当なプロファイルに基づく最適化は、より多くの回数実行される呼び出しサイトで優先的にインライン化することです。これにより、よりコールドなコードが小さくなり、最初のロードと修正のオーバーヘッドが少なくなり、(できれば) 命令の中断が少なくなります。私よりもはるかに多くのコンパイラの知識を持っている誰かが、それが良いかどうかについて一生懸命考えたでしょう。プロファイルに基づく最適化、したがって、それを実装するかどうかを決定しました。

于 2012-06-12T15:21:41.643 に答える
3

アセンブリレベルに手動で調整して、特定のコード行をキャッシュにロックすることを含めない限り、1つの大きな関数と複数の小さな関数の間に大きな実行の違いは見られません。どちらの場合も、実行する作業量は同じであり、それがボトルネックになります。

ただし、物事を複数の小さな関数に分割すると、保守が容易になり、読みやすくなります。特に、最初に行ったことを忘れてしまった6か月後はなおさらです。

于 2012-06-12T15:19:06.653 に答える
0

関数のサイズがアプリケーションのボトルネックになることはほとんどありません。関数で何をするかは、物理的なサイズよりもはるかに重要です。コンパイラが大きな関数 (つまり、インライン化) では実行できない小さな関数で実行できることがいくつかありますが、通常、これはとにかく大きな違いではありません。

コードをプロファイリングして、実際のボトルネックがどこにあるかを確認できます。大きな関数を呼び出すことは問題ではないと思います。

ただし、コードを読みやすくするために、関数をより小さな関数に分割する必要があります。

于 2012-06-12T15:18:02.493 に答える
-1

それは実際には関数のサイズではなく、その中で何をするかについてです。何をするかに応じて、それを最適化する方法があるかもしれません。

于 2012-06-12T15:19:03.450 に答える