2015-04-24 2 views
2

Je comprends que le modulus operation peut être optimisé en utilisant un peu & magie sage où le diviseur est une puissance de 2 ...Comment l'opérateur modulo est-il implémenté dans la JVM HotSpot?

  • et sans doute ce une optimisation que le compilateur JIT fait?
+0

Il n'y a pas d'opérateur modulo en Java. ''% Est définie comme le [opérateur reste] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.17.3). – EJP

+0

En effet, Merci de remarquer que sur –

Répondre

-1

Voici un échantillon extrait de code

public class Test { 

    public static void main(String[] args) { 
     int a=103; 
     int b=5; 
     int c=a%b; 
     } 
    } 

Maintenant, si vous voyez le code compilé de celui-ci, vous verrez

public static void main(java.lang.String[]); 
    flags: ACC_PUBLIC, ACC_STATIC 
    Code: 
    stack=2, locals=4, args_size=1 
     0: bipush  103 
     2: istore_1 
     3: iconst_5 
     4: istore_2 
     5: iload_1 
     6: iload_2 
     7: irem 
     8: istore_3 
     9: return 

bipush- pousser un octet sur la pile comme une valeur entière istore_1-Met un int hors de la pile et le stocke dans une variable locale, dans l'image en cours.

et 3: iconst_5 constante entière est poussé sur la pile

istore_2 fait la même chose que istore_1 variable nommée simplement changé.

Ensuite 5: iload_1 et 6:iload_2 les deux variables sont à nouveau poussés sur la pile pour les opérations

now at 7:irem the remainder operator works which you are calling as modulo. 

Maintenant, comment fonctionne les opérateurs Remainder. C'est Pops deux ints (valeur de a et b) de la pile d'opérandes, divise a par b, calcule le reste et repousse le reste int sur la pile. Le reste est (b - ((a/b) * b)). C'est ce qui est utilisé par l'opérateur% en Java.

+0

Ne pas utiliser citation mise en forme pour le texte non cité. – EJP

+0

@EJB Merci pour Suggestion édité .. Si vous trouvez toujours qu'il n'est pas correctement formaté .. S'il vous plaît le formater :) –

+1

Je l'avais déjà fait, et j'ai répété l'effort. Il n'y a pas besoin de caractères gras ici. Ce n'est pas une publicité. – EJP

3

Oui, un modulo x % pow(2, n) peut être réalisé en utilisant x & ((1 << n) - 1)

Mais le% -operator en java peut donner des résultats différents si x est négatif, donc substituer aveuglément un pour l'autre peut casser le code. Lorsque & -variant est communément utilisé, il est plus proche sémantiquement de ce qui est utilisé dans l'assembleur/C et la signature n'est généralement pas voulue/prise en compte dans ce cas. Quant à savoir si le JIT optimise% à &, la réponse est: cela dépend entièrement du JIT - et c'est une cible en mouvement.

Dans le cas où x % y y est pas assez difficile sa constante pour détecter si y est une puissance de 2, donc vraisemblablement ce cas n'est pas optimisable parce que la détection, il est très difficile, voire impossible. Si y est une constante, le JIT a encore la preuve que x n'est pas négatif - ou insère une condition similaire à result = x < 0 ? x % y : x & (y-1). Cela peut ou non se faire, en fonction de JIT en question et aussi en fonction de la plate-forme. Au moins Hotspot est connu pour utiliser différentes optimisations pour différents processeurs (du même ISA, à savoir AMD vs Intel) dans certains cas.

2

J'ai passé du temps sur cette question, en écrivant ce blog post avec tous les détails.

En bref:

  • Le JDK HotSpot 1.8 irem (int mod) est ~ 20% plus lent que l'affaire n & (pow2-1)
  • Le JDK HotSpot 1.8 frem (float mod) est 3 fois plus lent
  • Vous le kilométrage varie en fonction des passes JIT, donc le bénéfice pour Int est minime

Donc, il y a un avantage évident à ne pas faire mod sur les doubles, et vous pourriez obtenir un certain avantage avec les dividendes entiers naturels et la puissance de 2 diviseurs.