2017-05-02 13 views
1

가상 벽 노드에서 다음 코드를 실행하고 있습니다. 이 노드에는 32 개의 Intel Xeon E7/E5 코어와 128GB의 RAM이 있습니다. CPU 사용량을 모니터링하면 노드가 최대 강도로 작동하는 것으로부터 멀리 떨어져 있음을 알 수 있습니다. 이 문제는 노드 크기로 인해 대부분의 분기 결합 문제와 다릅니다. 노드가 여러 코어에 20 % + CPU로드를 가지면 병렬 처리의 징후가 나타나기도하지만 더 많은 리소스를 사용할 수는 없습니다.모든 CPU 코어를 사용하지 않는 Java ForkJoinPool

일부 컨텍스트를 제공하려면; 문제는 111 노드 (Parcs/parken)의 그래프에서 최대화 문제입니다. 많은 수의 난자가 각 공원 내에 숨어 있습니다. 이 숫자는 매 초마다 기하 급수적으로 떨어집니다. 목표는 시간이 끝나기 전에 가능한 한 많은 알을 얻는 것입니다. 'opl'은 greedy 알고리즘을 사용하여 찾은 솔루션이므로 재귀 트리를 좁히기 위해 동시에 발견 할 수있는 탐욕 알고리즘보다 5 개 이하의 계란을 찾았을 때만 재귀를 허용합니다.

저는 (멀티) 스레딩에 익숙하지만 전문가는 아닙니다. 전에 많은 ForkJoinPools를 사용하지 않았습니다. 또한 ForkJoinPool 매개 변수를 16/32로 조작하려고 시도했지만 성공하지 못했습니다.

Example of current core-load

홈페이지 :

Algoritmes.AlgoritmeRecursive.run(new AlgoritmeRecursive(parken, tabel, opl, 22, 1000, 0, 0))); 

클래스 : 나 자신이 잘 알고 모르겠지만,이 ar.join()에 통화가 RecursiveTask을 만들 것입니다 수

public static class AlgoritmeRecursive extends RecursiveTask<Double> { 
    private ArrayList<Park> parken = new ArrayList<Park>(); 
    private double[][] afstandenTabel; 
    private double[][] oplossing; 
    private int startpark; 
    private double duur; 
    private double eieren; 
    private int time; 

    AlgoritmeRecursive(ArrayList<Park> parken, double[][] afstandenTabel, double[][] oplossing, int startpark, double duur, double eieren, int time) { 
     for (Park p : parken) { 
      this.parken.add(new Park(p)); 
     } 
     this.afstandenTabel = afstandenTabel; 
     this.oplossing = oplossing; 
     this.startpark = startpark; 
     this.duur = duur; 
     this.eieren = eieren; 
     this.time = time; 
    } 

    public static double run(AlgoritmeRecursive ar) { 
     ForkJoinPool pool= new ForkJoinPool(); 
     return pool.invoke(ar); 
    } 

    protected Double compute() { 
     if (duur < 1.0) return eieren; 

     double gevonden = 0; 

     /* startpark zoeken adhv gegeven naam */ 
     for (Park p : parken) { 
      if (p.getId() == startpark) { 
       gevonden = p.verwachtAantalEieren(40, 0); 
       p.updateEggs(p.getEggs() * exp((-1.0/10800.0) * ((p.getStartEggs()/20.0) + 40.0))); 
      } 
      else { 
       p.updateEggs(p.getEggs() * exp((-1.0/10800.0) * (p.getStartEggs()/20.0))); 
      } 
     } 
     double score = eieren; 
     for (Park p : parken) { 
      if (p.getId() == startpark && eieren >= (oplossing[1000-(int)duur][1] - 5)) { 
       AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, startpark, duur-1, eieren + gevonden, time+1); 
       ar.fork(); 
       double res = ar.join(); 
       if(res > score) score = res; 
      } 
      else if (duur-afstandenTabel[startpark][p.getId()] > 60.0 && time > 120.0 && eieren >= oplossing[1000-(int)duur][1] && gevonden < p.verwachtAantalEieren(40,afstandenTabel[startpark][p.getId()])){ 
       AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, p.getId(), duur-afstandenTabel[startpark][p.getId()], eieren, 0); 
       for (Park p2 : ar.parken) { 
        p2.updateEggs(p2.getEggs() * exp((-1.0/10800.0) * (p2.getStartEggs()/20.0) * (afstandenTabel[startpark][p.getId()]-1))); 
       } 
       ar.fork(); 
       double res = ar.join(); 
       if(res > score) score = res; 
      } 
     } 
     return score; 
    } 
    public double exp(double x) { 
      x = 1d + x/256d; 
      x *= x; x *= x; x *= x; x *= x; 
      x *= x; x *= x; x *= x; x *= x; 
      return x; 
    } 
} 
+0

가상 벽이란 무엇입니까? –

답변

0

하위 작업이 완료 될 때까지 기다리시겠습니까? 이 경우 이전 작업이 끝나기 전에 다른 작업이 시작되지 않습니다.

실행중인 작업을 목록에 저장 한 다음 나중에 참가시킬 수 있습니다. 그것은 당신이 그들을 기다리기 전에 모든 하위 작업이 시작되기를 바랍니다.

for (...) { 
     // ar <- create sub-problem 
     ar.fork(); 
     double res = ar.join(); 
     // Use result 
    } 

문제 : 나는 문제가이 알고리즘의 재귀 부분이 같다고는 생각

List<AlgoritmeRecursive> tasks = new ArrayList<>(); 

for (Park p : parken) { 
    if (p.getId() == startpark && eieren >= (oplossing[1000-(int)duur][1] - 5)) { 

     AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, startpark, duur-1, eieren + gevonden, time+1); 
     ar.fork(); 
     tasks.add(ar); // Adding the running task to the list. 

    } else if (duur-afstandenTabel[startpark][p.getId()] > 60.0 && time > 120.0 && eieren >= oplossing[1000-(int)duur][1] && gevonden < p.verwachtAantalEieren(40,afstandenTabel[startpark][p.getId()])){ 

     AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, p.getId(), duur-afstandenTabel[startpark][p.getId()], eieren, 0); 
     for (Park p2 : ar.parken) { 
      p2.updateEggs(p2.getEggs() * exp((-1.0/10800.0) * (p2.getStartEggs()/20.0) * (afstandenTabel[startpark][p.getId()]-1))); 
     } 
     ar.fork(); 
     tasks.add(ar); // Adding the running task to the list. 

    } 
} 

double score = eieren; 
for(AlgoritmeRecursive task : tasks) { 
    double res = ar.join(); 
    if(res > score) score = res; 
} 

return score; 
0

이 같은

뭔가 (compute에서 두 번째 루프를 수정) 당신이 포크를하고 즉시 결합 할 때, 두 개 이상의 하위 문제가 동시에 실행되는 범위가 없다는 것입니다. 이것은 클래식 스레드에서 이와 같이 작업 한 경우와 동일합니다.

Thread t = new Thread(someRunnable); 
    t.start(); 
    t.join(); 

새 스레드를 시작하고 새 스레드가 완료 될 때까지 즉시 현재 스레드를 차단합니다. 즉 이며, 실제로는 단일 스레드입니다. 다음을 수행하는 것이 더 효율적입니다.

someRunnable.run(); 

한 루프에서 분기를 수행하고 다른 루프에서 결합을 시도하십시오.

+0

감사합니다. 힙 크기 확장 (-Xmx64G)으로 모든 코어를 사용하도록 권장합니다. 이제 StackOverflow 오류가 발생하지만 아마도 -Xmx 설정과 관련이 있습니다. 다시 한번 감사드립니다! –