3

セッターで次のような例をどこかで(おそらくGithubで)見たのを覚えています:

void MyClass::setValue(int newValue)
{
    if (value != newValue) {
        value = newValue;
    }
}

私にはあまり意味がありませんが、パフォーマンスが向上するかどうかは疑問です。

4

4 に答える 4

7

には意味がありませんscalar typesが、一部の型には意味があるかもしれませんuser-defined(型が本当に「大きい」か、その代入演算子が「難しい」作業を行うことができるため)。

于 2013-05-09T21:32:37.130 に答える
4

実際に判断できる唯一の方法は、さまざまな代替案を実際にテストすることです (コードのベンチマークおよび/またはプロファイリング)。異なるコンパイラ、異なるプロセッサ、およびそれを呼び出す異なるコードは、大きな違いを生みます。

一般に、「単純な」データ型 (int、double、char、ポインターなど) の場合は意味がありません。プロセッサにとってコードが長く複雑になるだけです[少なくともコンパイラがあなたが求めていることを実行する場合-「これは意味がありません。このチェックを削除しましょう-私は依存しません。つまり、多くの場合、コンパイラーはあなたよりも賢いですが、コンパイラーの生活をより困難にすることは、より良いコードにつながることはほとんどありません]。

編集:さらに、簡単に比較できるものを比較することは理にかなっています。データが等しい場合にデータを比較するのが難しい場合 (たとえば、長い文字列が等しい場合、両方の文字列から多くの読み取りが必要になります [または同じ文字列で始まり、最後の数文字だけが異なる文字列])。 . したがって、節約はほとんどありません. 多くの場合ほとんどすべてが同じであるメンバーの束を持つクラスにも同じことが当てはまりますが、1つまたは2つのフィールドはそうではありません.一意である必要がある整数の顧客 ID を持つ場合、顧客 ID だけを比較するのは「安く」なりますが、顧客の名前、住所、電話番号、および顧客の他のデータをコピーするのは高くつきます。 [もちろん、この場合、(スマート) ポインターまたは参照ではないのはなぜですか?].

データが異なるプロセッサ間で「共有」されている場合 (複数のスレッドが同じデータにアクセスしている場合)、少しは役立つかもしれません [特に、この値が頻繁に読み取られ、以前と同じ値で書き込まれることが多い場合]。これは、他のプロセッサのキャッシュから古い値を「追い出す」のはコストがかかるためであり、実際に何かを変更した場合にのみそれを実行したいからです。

そしてもちろん、パフォーマンスのホット パスの最前線にあることがわかっているコードで作業しているときに、パフォーマンスを心配しても意味がありません。それ以外の場合は、コードをできるだけ読みやすく、できるだけ明確かつ簡潔にすることが常に最良の選択です。これにより、通常、コンパイラは実際に何が起こっているかを判断し、最良の最適化結果を保証できます。

于 2013-05-09T21:50:23.673 に答える
4

命令パイプラインが深ければ深いほど (少なくとも Intel プラットフォームではますます深くなるだけです)、分岐予測ミスのコストが高くなります。

分岐が予測を誤った場合でも、予測を誤ったパスからの一部の命令がパイプラインを通過します。これらの命令に対して実行されたすべての作業は、分岐が正しく予測されていれば実行されなかったため、無駄になります。

そうです、 ifint 彼のコードを追加すると、実際にパフォーマンスが低下する可能性があります。書き込みは、おそらく長時間にわたって L1 キャッシュされます。書き込みを可視化する必要がある場合は、操作をインターロックして開始する必要があります。

于 2013-05-09T21:50:30.490 に答える
2

このパターンは、API がシグナルとスロットに大きく基づいている Qt で一般的です。このパターンは、循環接続の場合に無限ループを回避するのに役立ちます。

@remus-rusanu と @mats-petersson が指摘したように、シグナルが存在しない場合、このコードはパフォーマンスを低下させるだけです。

于 2013-05-10T02:52:37.457 に答える