Thomas Kramer

IT-COW | Dezember 2011

Modulo-Operator vs. bitweises Modulo

By Administrator at Dezember 14, 2011 14:13
Filed Under: Programmierung allgemein

Ich wollte doch auch einmal testen um wieviel schneller die bitweise Modulo-Operation gegenüber dem 32-Bit-Modulo-Operator wirklich ist. Nachfolgend meine Testergebnisse für jeweils eine Milliarde Modulo-Operationen auf einem 32-Bit-System:

 

7637 ms Zeit benötigt für Modulo-Berechnungen mittels 32-Bit-%-Operator.
350282 ms Zeit benötigt für Modulo-Berechnungen mittels 64-Bit-Modulo-Funktion IEEEremainder().
1624 ms Zeit benötigt für bitweise Modulo-Berechnungen.

 

Die bitweise Modulo-Operation ist demnach auf meinem Testrechner um das drei- bis vierfache schneller gegenüber dem 32-Bit-Modulo-Operator % und nochmal viel schneller gegenüber der 64-Bit-Modulo-Funktion IEEEremainder(). Der prozentuale Geschwindigkeitsgewinn ist beachtlich, aber heutige Prozessoren sind so schnell das es keine große Rolle mehr spielt - eine Ausnahme bilden mit Millionen Modulo-Operationen die (rollenden) Hash-Funktionen.

 

Außerdem ist gerade bei 64-Bit-Datentypen die bitweise Modulo-Operation zu bevorzugen, allerdings funktioniert sie nur mit Zweierpotenzen als Divisor.

 

Bei dem Modulo-Operator % sollte man immer überprüfen wie die native Implementierung negative Zahlen verarbeitet, denn das ist je nach System unterschiedlich.

 

Ergänzung: Zumindest im .NET-Framework liefert die IEEEremainder-Funktion zwar das gleiche Ergebnis wie der Standard-Modulo-Operator, aber die Formeln nach der sie den Rest bilden sind unterschiedlich.

 

In Java erfordert der %-Operator jedenfalls eine 32-Bit-Integerzahl, auf 64-Bit-long-Werte kann man ihn ohne bereichseinschränkenden int-Cast nicht anwenden.

 

import java.io.File;
import java.lang.Math;

public class Modulo {
   
  public static void main(String[] args)
  {
    /* Variante 1 mit 32-Bit-Modulo-Operator */
    long completeTimeBefore = System.currentTimeMillis();
    int temp = 0;
    for (int i=1;i<=1000000000;i++)
    {
       temp = i % 1024;
    }
    System.out.println("letzte Berechnung: " + temp);   
    long completeTimeAfter = System.currentTimeMillis();     
    long completeTimeDiff   = completeTimeAfter - completeTimeBefore;       
    System.out.println(completeTimeDiff + " ms Zeit benötigt für Modolu-Berechnungen mittels 32-Bit-%-Operator.\n");
   
    /* Variante 2 mit 64-Bit-Modulo-Operator */
    completeTimeBefore = System.currentTimeMillis();
    double temp2 = 0;
    for (int i=1;i<=1000000000;i++)
    {
       temp2 = java.lang.Math.IEEEremainder(i, 1024);
    }
    System.out.println("letzte Berechnung: " + temp2);   
    completeTimeAfter = System.currentTimeMillis();     
    completeTimeDiff   = completeTimeAfter - completeTimeBefore;       
    System.out.println(completeTimeDiff + " ms Zeit benötigt für Modolu-Berechnungen mittels 64-Bit-Modulo-Funktion IEEEremainder().\n");              
           
    /* Variante 3 mit bitweiser Modulo-Berechnung */
    completeTimeBefore = System.currentTimeMillis();   
    for (int i=1;i<=1000000000;i++)
    {
       temp2 = i & 1023;
    }   
    System.out.println("letzte Berechnung: " + temp2);
    completeTimeAfter = System.currentTimeMillis();     
    completeTimeDiff   = completeTimeAfter - completeTimeBefore;       
    System.out.println(completeTimeDiff + " ms Zeit benötigt für bitweise Modulo-Berechnungen.\n");   
  }   
}

 

Tag-Wolke

Monats-Liste