2017-05-02 18 views
1

仮想壁のノードで次のコードを実行しています。ノードには32個のIntel Xeon E7/E5コアと128GBのRAMがあります。 CPUの使用状況を監視すると、ノードは完全に強く動作していないことがわかります。この問題は、ノードサイズのために、ほとんどのフォーク結合問題とは異なります。ノードは複数のコアに20%+ CPU負荷を持ち、並列性の兆候を示すこともありますが、より多くのリソースを使用できるようには見えません。すべてのCPUコアを使用していないJava ForkJoinPool

いくつかのコンテキストを指定します。問題は、111ノード(Parcs/parken)のグラフ内の最大化問題です。多くの卵が各公園内に隠されています。その数は1秒ごとに指数関数的に減少します。目標は、時間が切れる前に可能な限り多くの卵を得ることです。 'opl'は私が欲張りアルゴリズムを使って見つけた解決法なので、私たちの再帰ツリーを絞り込むために、欲しいアルゴリズムが同時に見つけた卵より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であなたの第二のループを修正します)それをフォークしてすぐに結合すると、2つ以上のサブ問題が並行して実行されることはありません。あなたは、古典的なスレッドでこれをやったかのように、それは同じです:

新しいスレッドを開始し、
Thread t = new Thread(someRunnable); 
    t.start(); 
    t.join(); 

すぐに現在のスレッドをブロックし、新しいものが終了するまで、即ち、それはであり、事実上シングルスレッドである。これを行う方が効率的です:

フォークを1つのループで行い、別のループで結合してみてください。

+0

おかげさまで、ヒープサイズ(-Xmx64G)を拡張することで推奨されるaswelは、すべてのコアを使用するようにしました!今はStackOverflowのエラーが出ていますが、おそらく-Xmxの設定と関係があります。 おかげで再び! –

関連する問題