です私たちが整数引数を持っている%
ではなくfmod
の使用をなぜ疑問に思っていますか?なぜなら、なぜですか?はいくつかの古いSRCコードに次の行を見つけ整数係数の計算のための速い%よりFMOD
int e = (matrix[i]) % n;
fmod
を%
以上に選択するとパフォーマンス上の理由があるのでしょうか、それともちょっと変わったコードですか?
です私たちが整数引数を持っている%
ではなくfmod
の使用をなぜ疑問に思っていますか?なぜなら、なぜですか?はいくつかの古いSRCコードに次の行を見つけ整数係数の計算のための速い%よりFMOD
int e = (matrix[i]) % n;
fmod
を%
以上に選択するとパフォーマンス上の理由があるのでしょうか、それともちょっと変わったコードですか?
はおそらく
fmod
%
オーバー を選択するか、それがコードのちょうど奇妙なビットであるため、パフォーマンス上の理由があるだろうか?
fmod
は少し速く〜50サイクル以上、そうfmod
の関数呼び出しとint <---> double
変換のコストを償却することができます(たとえば)かかり高遅延IDIV
命令、とのアーキテクチャ上のかもしれません。
Agner's Fog instruction tablesによれば、AMD K10アーキテクチャのIDIV
は24~55サイクルかかる。現代のIntel Haswellと比較すると、レイテンシの範囲は22-29サイクルとなっていますが、依存関係のチェーンがない場合は、インテルの8~11クロックサイクルでは逆のスループットがはるかに優れています。
実験(および非常に反直感的)、fmod
は%
より速い - 少なくともAMDのPhenom(TM)II X4 955 6400とBogoMips値に。
#include <math.h>
#include <stdio.h>
int main()
{
int volatile a=10,b=12;
int i, sum = 0;
for (i = 0; i < 1000000000; i++)
sum += a % b;
printf("%d\n", sum);
return 0;
}
時間の実行::9.07秒をここでの手法のいずれかを使用する2つのプログラム、両方が同じコンパイラ(GCC)と同じオプション(cc -O3 foo.c -lm
)でコンパイルされ、同じハードウェア上で実行しましたがされています。
#include <math.h>
#include <stdio.h>
int main()
{
int volatile a=10,b=12;
int i, sum = 0;
for (i = 0; i < 1000000000; i++)
sum += (int)fmod(a, b);
printf("%d\n", sum);
return 0;
}
実行時間:8.04秒
fmod
は、選択したアーキテクチャの整数除算よりも少し速いかもしれません。
注しかしn
は、コンパイル時に知られている非ゼロ値を有する場合、matrix[i] % n
整数モジュラスおよび浮動小数点モジュラスのいずれよりもはるかに高速でなければならない小さな調整、との乗算としてコンパイルされること。
もう1つ興味深い違いは、n == 0
とINT_MIN % -1
の動作です。整数モジュラス演算はオーバーフロー時に未定義の動作を呼び出し、多くの現在のアーキテクチャ上でプログラムが異常終了する結果になります。逆に、浮動小数点弾性率は、これらのコーナーケースを有していない、結果は、-Infinity
、+Infinity
あるNan
matrix[i]
と-INT_MIN
、すべてint
の範囲と背面int
に実装定義されている変換を超える値に応じて、通常はしません異常なプログラムの終了を引き起こします。これは、元のプログラマーがこの驚くべき解決方法を選択した理由です。
私の特定のシナリオでは、n> 0、通常<〜1000であり、コンパイル時定数ではありません。私は%のfmodを交換しました。私のインテルでは、私は40%のスピードアップを見ました。さらなる洞察をいただきありがとう – bph
'fmod'は' double'に変換されて戻される浮動小数点値を使用しています。だから:** no **。整数演算の場合は、 '%'演算子を使用してください。 –
prob何かが遅い?私は、C文から対応するアセンブリを生成することはあまりできませんが、fmodを% – bph