2017-08-23 2 views
-1

Salut at-on des références sur les performances/coûts relatifs des opérateurs mathématiques Java?Performance relative Java des opérateurs mathématiques

Idéalement quelque chose comme dans le code complet 2 (que je n'ai pas sous la main en ce moment)

où il pourrait ressembler à ceci:

  • plus: 1
  • soustraction
  • : 2
  • multiplication: 10
  • division
  • : 100
  • logarithme: 600
  • exposant: 500

Merci.

+2

Pouvez-vous être plus explicite à propos de votre question? Que signifient ces chiffres? Cela signifie-t-il quelque chose comme "* la division est environ 100 fois plus lente que l'addition *"? Sonorités très plate-forme dépendait si vous me demandez. Cela dépend en grande partie de la façon dont votre code ressemble, du nombre d'optimisations générées par la ** JVM ** et de l'apparence du code machine résultant et de la manière dont il est exécuté par votre processeur. Certainement pas facile de créer des repères significatifs. – Zabuza

+0

Par exemple, notez que de nombreux processeurs utilisent ** des tables de recherche ** pour certaines multiplications fréquentes et d'autres tâches (ils ont les résultats précalculés et stockés dans une table), ils peuvent ainsi retourner une réponse instantanément. Ce champ est tellement plein d'optimisations que vous pouvez difficilement contrôler dans un benchmark. – Zabuza

+0

Juste à titre d'exemple, si vous écrivez 'int sum = 0; pour (int i = 0; i <100; i ++) {sum ++; } ', la ** JVM ** convertira ceci en l'instruction unique' int sum = 100; 'dans le bytecode (fichier * .class *). Il semble alors que l'addition serait extrêmement rapide. Il est si facile de tomber dans de telles suppositions fausses. – Zabuza

Répondre

0

Je fouetté ensemble ce quickie, le code de test informel, non scientifique complètement:

import java.util.function.BinaryOperator; 

public class Test { 
    private static void test(String desc, BinaryOperator<Double> op, double a, double b, long startIter) 
    { 
     long maxIter = startIter; 
     long elapsed; 
     do { 
      maxIter *= 2; 
      long start = System.currentTimeMillis(); 
      for (long niter = 0; niter < maxIter; ++niter) { 
       double res = op.apply(a, b); 
      } 
      elapsed = System.currentTimeMillis() - start; 
     } while (elapsed <= 10_000); 
     System.out.printf("%-15s/sec\t%g\n", 
      desc, (maxIter * 1000.0)/elapsed); 
    } 

    public static void main(String[] arg) 
    { 
     test("Addition (double)", (Double a, Double b) -> { 
      return a + b; 
     }, 483902.7743, 42347.775, 10_000_000); 
     test("Subtraction (double)", (Double a, Double b) -> { 
      return a - b; 
     }, 483902.7743, 42347.775, 10_000_000); 
     test("Multiplication (double)", (Double a, Double b) -> { 
      return a * b; 
     }, 483902.7743, 42347.775, 1_000_000); 
     test("Division (double)", (Double a, Double b) -> { 
      return a/b; 
     }, 483902.7743, 42347.775, 1_000_000); 
     test("Log10", (Double a, Double b) -> { 
      return Math.log10(a); 
     }, 483902.7743, 42347.775, 1_000_000); 
     test("LogE", (Double a, Double b) -> { 
      return Math.log(a); 
     }, 483902.7743, 42347.775, 1_000_000); 
     test("Power", (Double a, Double b) -> { 
      return Math.pow(a, b); 
     }, 483902.7743, 12, 100_000); 
    } 
} 

Dans mon environnement Java standard --- 8 JDK, Intel Core2 Quad Q8300 @ 2.5GHz --- une sortie brute représentant ce test est la suivante:

Addition (double)/sec 6.18619e+08 
Subtraction (double)/sec 4.10651e+08 
Multiplication (double)/sec 3.27010e+07 
Division (double)/sec 3.22215e+07 
Log10   /sec 1.99330e+07 
LogE   /sec 1.99206e+07 
Power   /sec 8.67870e+06 

Conversion à la performance relative nous avons:

Addition   1.0 
Subtraction  1.5 
Multiplication 18.9 
Division   19.2 
Log10   31.0 
LogE    31.1 
Power   71.3 

Comme d'habitude, votre kilométrage peut varier.

+0

Merci, c'est plus ou moins ce que je cherchais! Une chose que je me demande toujours est de savoir s'il vaudrait mieux utiliser Random pour obtenir les nombres à chaque itération, car je suis inquiet (peut-être injustifié) des optimisations du compilateur avec le même nombre (mise en cache) ou peut-être que nombre est vraiment facile de prendre le journal de, par exemple en raison d'une table de recherche (rappel à ce que Zabuza a dit) –

+0

Oui, il serait probablement donner une image plus réaliste d'utiliser une variété d'arguments différents. Je ne m'attendrais pas à des changements spectaculaires dans les rangs globaux, juste une meilleure estimation de la performance relative. Par exemple, vous pourriez trouver que la multiplication est "vraiment" de 19 ou 14 additions plutôt que 18, mais il n'y aura jamais 3 ou 4 additions, et les logs pourraient "vraiment" être 28 ou 34 additions mais ne seront probablement jamais moins qu'une multiplication ... –

+0

-1 Essayez la commande "Multiplication, Soustraction, Addition" pour voir pourquoi. Google pour le site d'appel bi- et mégamorphique à comprendre. Utilisez JMH pour le faire correctement. – maaartinus