まず、問題の文脈:私は非常に大きなグラフを保存するには約4GB必要です。約3Mのノードと34Mのエッジ。私のプログラムは、この大きなグラフを取り、そこから小さなグラフを再帰的に作成します。再帰の各レベルには、元のグラフとオリジナルから作成されたグラフという2つのグラフがあります。この再帰は、グラフが約10ノードという非常に小さなグラフに縮小されるまで続きます。大きな地図をメモリに保存する
プログラムの実行全体にこれらのグラフが必要なので、メモリ効率は私のアプリケーションにとって非常に重要です。
は今ここに私は現在抱えている問題です: これは、1つの大きなから小さなグラフを作成するためのアルゴリズムである:私はこれを行うとき
public static Graph buildByTriples(Graph g, ArrayList<Integer> seeds) {
ArrayList<Edge> edges = new ArrayList(g.getEdgeCount());
for (int i = 0; i < g.size(); i++) {
for (Edge e : g.adj(i)) {
int v = e.getEndpoint(i);
if (i < v) {
edges.add(e);
}
}
}
Table<Integer, Integer, Double> coarseEgdes = HashBasedTable.create(seeds.size(),seeds.size());
//compute coarse weights
edges.stream().forEach((e) -> {
int v = e.getV();
int u = e.getU();
if (g.isC(u) && g.isC(v)) {
addToTable(coarseEgdes, u, v, e.getWeight());
}else if(!g.isC(u) && g.isC(v)){ //F-C
for(Edge cEdge: g.cAdj(u)){//get coarse neighbors of the fine edges
int nb = cEdge.getEndpoint(u);
if(nb != v){
addToTable(coarseEgdes, v, nb, cEdge.getPij() * e.getWeight());
}
}
}else if(g.isC(u) && !g.isC(v)){//C-F
for(Edge cEdge: g.cAdj(v)){//get coarse neighbors of the fine edges
int nb = cEdge.getEndpoint(v);
if(nb != u){
addToTable(coarseEgdes, u, nb, cEdge.getPij() * e.getWeight());
}
}
}else{//F-F
for(Edge cEdgeU: g.cAdj(u)){//get coarse neighbors of the fine edges
int uNb = cEdgeU.getEndpoint(u);
for(Edge cEdgeV: g.cAdj(v)){
int vNb = cEdgeV.getEndpoint(v);
if(uNb != vNb){
addToTable(coarseEgdes, uNb, vNb, cEdgeU.getPij() * e.getWeight() * cEdgeV.getPij());
}
}
}
}
});
return createGraph(g, coarseEgdes); //use the edges to build new graph. Basically loops through coarseEdges and add edge and weight to the new graph.
}
private static void addToTable(Table<Integer, Integer,Double> tbl, int r, int c, double val){
int mn = Math.min(r, c);//the smaller of the two nodeIds
int mx = Math.min(r, c);//the largest of the two nodeId
if(tbl.contains(mn, mx)){
tbl.put(mn, mx, tbl.get(mn, mx) + val);
}else{
tbl.put(mn, mx,val);
}
}
は今、私はすぐにメモリ不足に。私はYourKitでアプリケーションのプロファイリングを行い、メモリ使用量は屋根を越えています(実行前に6GBを超えています)。 coarseEdges
は本当に大きくなることがあります。大規模なデータセットで拡張されたメモリ内のMap実装が優れていますか?または、保存せずにこれを行うより良い方法がありますか?coarseEdges
?
PS:一定時間内にグラフがエッジ(u、v)を取得できないことに注意してください。これは基本的にリストのリストで、これは私のアプリケーションの他の重要な部分のパフォーマンスを改善します。
'Graph'の実装使っていますか? 'グラフ'インターフェースは 'com.google.guava:guava:20.0-SNAPSHOT'で利用可能ですが、そのAPIにはこれらのメソッドはありません。どのようなメソッドが何かを理解することなくあなたのアルゴリズムに従うのは少し難しいと思っています。 – mfulton26
グラフは私の実装です。私はあなたの参照のためのグラフ実装を含めました。 – unekwu
この質問はここでもうまくいきますが、便利な一般的なアドバイスが得られる[CR](http://codereview.stackexchange.com/questions/tagged/java)にも適しています。サイドノート:あなたの 'next'と' hasNext'は壊れています(一般的なシナリオでは動作しますが)。 – maaartinus