Ich habe gerade die folgende Zeile in einem alten src-Code gefunden:
%Vor% Dabei ist matrix
ein Array von int
und n
ist ein size_t
Ich frage mich, warum wir fmod
anstatt %
verwenden, wo wir ganzzahlige Argumente haben, also warum nicht:
Könnte es einen Leistungsgrund für die Wahl von fmod
über %
geben oder ist es nur ein seltsames Stück Code?
Könnte es einen Leistungsgrund für die Wahl von
fmod
über%
geben? oder ist es nur ein komisches Stück Code?
Die fmod
könnte bei Architekturen mit der Anweisung IDIV
mit hoher Latenz etwas schneller sein, die etwa 50 Zyklen oder mehr benötigt, also können fmod
Funktionsaufrufe und int <---> double
Konvertierungskosten sein amortisiert.
Laut Agners Fog Anweisungstabellen dauert IDIV
auf AMD K10 Architektur 24-55 Zyklen. Im Vergleich mit dem modernen Intel Haswell ist der Latenzbereich 22-29 Zyklen. Wenn keine Abhängigkeitsketten vorhanden sind, ist der reziproke Durchsatz bei Intel 8-11 Taktzyklen viel besser.
Experimentell (und ziemlich kontraintuitiv) ist fmod
schneller als %
- mindestens auf AMD Phenom (tm) II X4 955 mit 6400 bogomips . Hier sind zwei Programme, die eine der Techniken verwenden, die beide mit dem gleichen Compiler (GCC) und den gleichen Optionen ( cc -O3 foo.c -lm
) kompiliert wurden und auf der gleichen Hardware laufen:
Laufzeit: 9,07 Sek.
%Vor%Laufzeit: 8,04 Sek.
fmod
ist möglicherweise ein kleines bisschen schneller als die Ganzzahldivision auf ausgewählten Architekturen.
Beachten Sie jedoch, dass, wenn n
zum Kompilierungszeitpunkt einen bekannten Wert ungleich Null hat, matrix[i] % n
als eine Multiplikation mit einer kleinen Anpassung kompiliert würde, die viel schneller sein sollte als sowohl der Ganzzahl-Modul als auch der Gleitkomma-Modul.
Ein weiterer interessanter Unterschied ist das Verhalten in n == 0
und INT_MIN % -1
. Die Integer-Modulo-Operation ruft bei einem Überlauf ein undefiniertes Verhalten auf, das bei vielen aktuellen Architekturen zu einer abnormalen Programmbeendigung führt. Umgekehrt hat das Gleitkomma-Modul nicht diese Eckfälle, das Ergebnis ist +Infinity
, -Infinity
, Nan
abhängig von dem Wert von matrix[i]
und -INT_MIN
, alle überschreiten den Bereich von int
und Die Konvertierung in int
ist implementiert, führt jedoch normalerweise nicht zu einem Programmabbruch. Dies könnte der Grund dafür sein, dass der ursprüngliche Programmierer diese überraschende Lösung gewählt hat.