2010-09-15 5 views
0

Je cours un programme très simple qui simule tour de Hanoi. J'imprime le temps nécessaire pour déplacer les disques n (20 à 30). Je vois un motif étrange. Il faut environ le même laps de temps pour déplacer n (nombre pair) et n + 1 disques. Et pour déplacer n + 2 disque il faut 4 fois de n disques. J'ai mis le programme ci-dessous. Je suppose qu'il y a une certaine optimisation en vm lorsque nous avons plusieurs appels de récursivité. Quelqu'un peut-il donner plus de lumière à ce sujet?comportement étrange lors de l'exécution de la tour de Hanoi

public class Hanoi { 
    public static void move(int n) { 
     if(n > 0) {   
      move(n-1); 
      move(n-1);    
     } 
    } 

    public static void main(String[] args) { 
     int N = 28; 
     move(12); 
     for(int n=18; n <= N; n++) { 
      long start = System.currentTimeMillis(); 
      move(n); 
      long end = System.currentTimeMillis(); 
      System.out.printf("n=%d t=%d i=%d\n",n, (end-start) , 10); 
     } 
    } 
} 
+0

Comme votre code a des récursions de queue, il est probable qu'il sera optimisé. –

Répondre

1

"Problème"? :-)

Si vous ajoutez des E/S ou des calculs décents à la méthode move, vous verrez que ce comportement disparaît. En outre, si vous effectuez simplement un appel récursif move, le programme se termine immédiatement. Ces deux anomalies de synchronisation sont dues à l'optimisation du compilateur et du JIT, comme l'a mentionné Gunner. Cette version de votre méthode move par exemple, a beaucoup plus attendu calendrier:

static int[] pieces = new int[100]; 
public static void move(int n) { 
    if (n > 0) { 
     // random memory operations 
     pieces[n - 1] = pieces[n]; 
     pieces[n] = pieces[n + 1]; 
     pieces[n + 1] = pieces[n + 2]; 
     move(n - 1); 
     move(n - 1); 
    } 
} 

Voici un article intéressant par IBM à propos tail recursion. Voici un autre blog posting sur le sujet.

+0

Mais ici l'optimisation est étrange. Par exemple, l'entrée n = 30 et 31 prennent approximativement le même temps. Mais n = 32 prend 4 fois 31, mais théoriquement cela devrait prendre deux fois de 31. – pranab

+0

Je ne peux pas l'expliquer. Peut-être que c'est en train de se dérouler et que N + 1 est vraiment N avec un autre appel en boucle alors que N + 2 est une différence assez importante pour l'optimiser différemment. Encore une fois, sans faire de véritable travail dans move(), et sans connaître les subtilités de JIT ou de l'optimiseur du compilateur, je ne peux pas le dire. – Gray