40

fooオブジェクト( an int、 a double、 custom struct、 aなど) を考えてみましょうclass。私の理解ではfoo、関数への参照渡し (または へのポインターを渡すだけfoo) は、ローカル コピーの作成を回避するため (大きい場合はコストがかかる可能性があります)、パフォーマンスが向上しますfoo

ただし、ここでの回答から、何が指されているかに関係なく、64ビットシステムのポインターは実際には8バイトのサイズを持つことが期待できるようです。私のシステムでは、afloatは 4 バイトです。それは、 iffooが type の場合、ポインタを渡すよりも値で渡す方が効率的であることを意味しますか (関数内で一方を他方よりも効率的に使用する他の制約がないことを前提としています)?floatfoo

4

5 に答える 5

35

「コスト」の意味と、操作に関するホスト システム (ハードウェア、オペレーティング システム) のプロパティによって異なります。

コストの尺度がメモリ使用量である場合、コストの計算は明らかです。コピーされているもののサイズを合計します。

測定が実行速度 (または「効率」) である場合、ゲームは異なります。ハードウェア (およびオペレーティング システムとコンパイラ) は、専用回路 (マシン レジスタとその使用方法) のおかげで、特定のサイズのものをコピーする操作のパフォーマンスに対して最適化される傾向があります。

たとえば、マシンが「スイート スポット」をもたらすアーキテクチャ (マシン レジスタ、メモリ アーキテクチャなど) を持っていることはよくあることです。あるサイズの変数をコピーするのが最も「効率的」ですが、より大きなまたは小さい変数をコピーするのは効率的です。そうではありません。小さなチャンクの複数のコピーを行う必要がある場合があるため、大きな変数はコピーに多くのコストがかかります。コンパイラは小さい値を大きい変数 (またはレジスタ) にコピーし、それに対して操作を実行してから、値をコピーして戻す必要があるため、小さいものはより多くのコストがかかる場合があります。

浮動小数点の例には、倍精度浮動小数点 (別名doubleC++) をネイティブにサポートするいくつかの Cray スーパーコンピューターが含まれ、単精度 (別名 C++) のすべての操作floatはソフトウェアでエミュレートされます。一部の古い 32 ビット x86 CPU も内部で 32 ビット整数を使用して動作し、16 ビット整数での操作には、32 ビットとの間の変換のために、より多くのクロック サイクルが必要でした (これは、最新の 32 ビットまたは 64 ビットでは当てはまりません)。ビット x86 プロセッサ (16 ビット整数を 32 ビット レジスタとの間でコピーしたり、32 ビット レジスタからコピーしたり、そのようなペナルティが少なくて済むため)。

非常に大きな構造体を値でコピーすることは、そのアドレスを作成してコピーするよりも効率が悪いことは、少し簡単です。ただし、上記のような要因により、「そのサイズのものを値でコピーするのが最善」と「そのアドレスを渡すのが最善」の交差点はあまり明確ではありません。

ポインターと参照は同様の方法で実装される傾向があります (たとえば、参照渡しはポインターを渡すのと同じ方法で実装できます) が、それは保証されません。

確認する唯一の方法は、それを測定することです。また、測定値はシステムによって異なることに注意してください。

于 2016-10-21T21:56:30.850 に答える
7

パフォーマンスが絶対的に重要な特定のシナリオをテストする必要がありますが、コンパイラに特定の方法でコードを生成させることには十分注意してください。

コンパイラのオプティマイザは、最終結果が同じであることが証明されている限り、任意の方法でコードを書き直すことができます。これにより、非常に優れた最適化が行われる可能性があります。

float を値で渡すには float のコピーを作成する必要があることを考慮してください。ただし、適切な条件下では、float を参照で渡すと、元の float を CPU 浮動小数点レジスタに格納し、そのレジスタを「参照」パラメータとして扱うことができます。関数に。対照的に、コピーを渡す場合、コンパイラはレジスタの内容を保持するためにコピーを格納する場所を見つける必要があります。オリジナルを保存します (これは特に再帰関数に当てはまります!)。

この違いは、インライン化できる関数に参照を渡す場合にも重要です。この場合、コピーされたパラメーターが元のパラメーターを変更できないことをコンパイラーが保証する必要がないため、参照によってインライン化のコストが削減される可能性があります。

言語によって、どのように実行したいかではなく、何を実行したいかを記述することに集中できるほど、コンパイラは、難しい作業を行うための創造的な方法を見つけることができます。特に C++ では、通常、パフォーマンスについて心配するのではなく、必要なものをできるだけ明確かつ簡単に記述することに集中するのが最善です。作業をどのように行うかを記述しようとすると、コンパイラがコードを最適化する仕事を実行できなくなることがよくあります。

于 2016-10-21T22:07:12.450 に答える