5

20-30 years ago arithmetic operations like division were one of the most costly operations for CPUs. Saving one division in a piece of repeatedly called code was a significant performance gain. But today CPUs have fast arithmetic operations and since they heavily use instruction pipelining, conditionals can disrupt efficient execution. If I want to optimize code for speed, should I prefer arithmetic operations in favor of conditionals?

Example 1

Suppose we want to implement operations modulo n. What will perform better:

int c = a + b;
result = (c >= n) ? (c - n) : c;

or

result = (a + b) % n;

?

Example 2

Let's say we're converting 24-bit signed numbers to 32-bit. What will perform better:

int32_t x = ...;
result = (x & 0x800000) ? (x | 0xff000000) : x;

or

result = (x << 8) >> 8;

?

4

3 に答える 3

2

簡単に手に入る成果物はすべて、コンパイラーの作成者やハードウェアを構築する人によって、すでに選択され、漬けられています。あなたがそのような質問をする必要があるような人なら、手動で何かを最適化できる可能性は低いでしょう.

20 年前には、比較的有能なプログラマーがアセンブリに落とし込むことで最適化を行うことができましたが、現在では、ターゲット アーキテクチャを専門とする専門家の領域です。また、最適化には、プログラムを知るだけでなく、プログラムが処理するデータを知る必要があります。すべてはヒューリスティックス、さまざまな条件下でのテストなどに帰着します。

単純なパフォーマンスの質問には、もはや単純な答えはありません。

于 2013-02-09T16:06:50.520 に答える
2

速度を最適化したい場合は、コンパイラに速度を最適化するように指示する必要があります。一般に、最新のコンパイラは、この分野で優れています。

まさにこの理由で、アセンブリ コードを元のソースに関連付けようとして驚かされることがあります。

読みやすくするためにソース コードを最適化し、コンパイラに最適な処理をさせます。

于 2013-02-09T15:53:16.787 に答える
2

例 #1 では、最初の例の方がパフォーマンスが良いと思います。コンパイラは、分岐を回避するためにビット操作のトリックを適用する可能性があります。ただし、コンパイラが推測できる可能性は非常に低いという知識を利用しています。つまり、合計は常に範囲内にある[0:2*n-2]ため、1 回の減算で十分です。

例 2 のように、2 番目の方法は最新の CPU では高速であり、従うのも簡単です。どちらのバージョンでも、賢明なコメントが適切です。(コンパイラーが最初のバージョンを 2 番目のバージョンに変換するのを見ても驚かないでしょう。)

于 2013-02-09T16:36:33.977 に答える