2017-02-08 1 views
-2

J'essaie de vérifier les performances du code suivant, mais chaque fois que j'obtiens un fonctionnement séquentiel donne de meilleures performances que la jointure de fourche.La jointure de la fourche ne donne pas une meilleure performance

Problème Je veux trouver entier max:

public class GetMaxIntegerProblem { 

    private final int[] intArray; 
    private int start; 
    private int end; 
    private int size; 

    public GetMaxIntegerProblem(int[] intArray, int start, int end) { 
     super(); 
     this.intArray = intArray; 
     this.start = start; 
     this.end = end; 
     size = end - start; 
    } 

    public int getMaxSequentially() { 
     int max = Integer.MIN_VALUE; 
     for (int i = start; i < end; i++) { 
      int n = intArray[i]; 
      max = n > max ? n : max; 
     } 
     return max; 
    } 

    public int getSize() { 
     return size; 
    } 


    public GetMaxIntegerProblem getMaxIntegerSubProblem(int subStart, int subEnd) { 
     return new GetMaxIntegerProblem(this.intArray, start + subStart, start + subEnd); 
    } 
} 

Mon action pour fourche rejoindre:

import java.util.concurrent.RecursiveAction; 


public class GetMaxIntegerAction extends RecursiveAction { 
    private final int threshold; 
    private final GetMaxIntegerProblem problem; 
    private int result; 

    public GetMaxIntegerAction(int threshold, GetMaxIntegerProblem problem) { 
     super(); 
     this.threshold = threshold; 
     this.problem = problem; 
    } 

    @Override 
    protected void compute() { 
     if (problem.getSize() < threshold) { 
      result = problem.getMaxSequentially(); 
     } else { 
      int midPoint = problem.getSize()/2; 
      GetMaxIntegerProblem leftProblem = problem.getMaxIntegerSubProblem(0, midPoint); 
      GetMaxIntegerProblem rightProblem = problem.getMaxIntegerSubProblem(midPoint + 1, problem.getSize()); 
      GetMaxIntegerAction left = new GetMaxIntegerAction(threshold, leftProblem); 
      GetMaxIntegerAction right = new GetMaxIntegerAction(threshold, rightProblem); 
      invokeAll(left, right); 
      result = Math.max(left.result, right.result); 
     } 

    } 

} 

Mon programme principal pour les essais:

import java.util.Random; 
import java.util.concurrent.ForkJoinPool; 

public class GetMaxIntegerMain { 

    public GetMaxIntegerMain() { 
     // TODO Auto-generated constructor stub 
    } 

    private Random random = new Random(); 

    private void fillRandomArray(int[] randomArray) { 
     for (int i = 0; i < randomArray.length; i++) { 
      randomArray[i] = random.nextInt(10000); 
     } 
    } 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     GetMaxIntegerMain mainexcution=new GetMaxIntegerMain(); 
     int arrayLength = 10_00_000; 
     int array[] = new int[arrayLength]; 
     mainexcution.fillRandomArray(array); 
     GetMaxIntegerProblem problem=new GetMaxIntegerProblem(array, 0, array.length); 
     //No. of times sequential & 
     //Parallel operation should be performed to warm up HotSpot JVM 
     final int iterations = 10; 
     long start = System.nanoTime(); 
     int maxSeq=0; 
     for (int i = 0; i < iterations; i++) { 
      maxSeq=problem.getMaxSequentially(); 
     } 
     long endSeq=System.nanoTime(); 
     long totalSeq=endSeq-start; 
     System.out.println(" time for seq "+(endSeq-start)); 

     System.out.println("Number of processor available: " + Runtime.getRuntime().availableProcessors()); 
     //Default parallelism level = Runtime.getRuntime().availableProcessors() 
     int threads=Runtime.getRuntime().availableProcessors(); 
     ForkJoinPool fjpool = new ForkJoinPool(64); 

     long startParallel = System.nanoTime(); 
     for (int i = 0; i < iterations; i++) { 
      GetMaxIntegerAction action=new GetMaxIntegerAction(5000, problem); 
      fjpool.invoke(action); 
     } 
     long endParallel = System.nanoTime(); 
     long totalP=endParallel-startParallel; 
     System.out.println(" time for parallel "+totalP); 
     double speedup=(double)(totalSeq/totalP); 
     System.out.println(" speedup "+speedup); 
     System.out.println("Number of steals: " + fjpool.getStealCount() + "\n"); 


    } 

} 

Chaque fois que je suis en cours d'exécution ce code, je reçois le code spécifique forkjoin prend 400% plus de temps. J'ai essayé avec une combinaison de seuil mais je ne réussis pas.

J'utilise ce code sur Processeur Intel Core i3 3,3 GHz 64 bits sous Windows 10.

Ce serait une aide précieuse si quelqu'un pouvait fournir des pointeurs sur ce problème.

+0

Vous utilisez un moyen inapproprié pour les performances d'estimation. Cela devrait être un test de micro-test. – Andremoniy

+0

http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – Andremoniy

+3

'new ForkJoinPool (64);'? Soit vous courez sur une bête, soit vous avez mal compris comment fonctionne FJP. – Kayaman

Répondre

0

Dans de très nombreux cas, il ne faut pas s'attendre à de meilleures performances lors de l'utilisation de la jointure de fourches, car les frais généraux de forking et de jointure peuvent devenir très importants. Voir, par exemple, cette discussion (principalement la deuxième moitié) https://www.youtube.com/watch?v=2nup6Oizpcw