グラフの最小スパニング ツリーを見つけるために、Boruvka のアルゴリズムを C++ で実装しています。このアルゴリズムは、各スーパーバーテックス (スーパーバーテックスは接続されたコンポーネントであり、最初の反復では単なる頂点です) の最小重みエッジを見つけて、MST に追加します。エッジが追加されると、接続コンポーネントが更新され、グラフ内のすべての頂点が 1 つの接続コンポーネントになるまで、find-min-edge と merge-supervertices プロセスが繰り返されます。
各スーパーバーテックスの find-min-edge は並列に実行できるので、OpenMP を使用してこれを実行したいと考えています。これは、omp for
並列find-minに使用したいループです。
int index[NUM_VERTICES];
#pragma omp parallel private(nthreads, tid, index, min) shared(minedgeindex, setcount, forest, EV, umark)
{
#pragma omp for
for(int k = 0; k < setcount; k++){ //iterate over supervertices, omp for here
min = 9999;
std::fill_n(index, NUM_VERTICES, -1);
/* Gets minimum edge for each supervertex */
for(int i = 0; i < NUM_VERTICES; i++) {
if(forest[i]->mark == umark[k]){ //find vertices with mark k
for(int j = 0; j < NUM_EDGES; j++) {
//check min edge for each vertex in the supervertex k
if(EV[j].v1==i){
if(Find(forest[EV[j].v1])!= Find(forest[EV[j].v2])){
if(EV[j].w <= min ){
min = EV[j].w;
index[k] = j;
break; //break looping over edges for current vertex i, go to next vertex i+1
}
}
}
}
}
} //end finding min disjoint-connecting edge for the supervertex with mark k
if(index[k] != -1){
minedgeindex.insert(minedgeindex.begin(), index[k]);
}
} //omp for end
}
私は OpenMP を初めて使用するため、現在、期待どおりに動作させることができません。
このコード ブロックで行っていることを簡単に説明します
setcount
。 は超頂点の数です。EV
すべてのエッジを含むベクトルです (Edge
は以前に定義した構造体でv1, v2, w
あり、接続する 2 つのノードとその重みに対応する属性を持ちます)。minedgeindex
はベクトルです。各スレッドが各連結成分の最小エッジを見つけ、最小エッジのインデックス (インデックス j in EV
) をベクトルminedgeindex
に同時に追加するようにします。minedgeindex
だから共有するべきだと思います。forest
は各頂点の構造体であり、umark
どのスーパーバーテックスにあるかを示すセット マークがあります。すべてのスーパーバーテックスをマークするために使用Union-Find
しますが、この omp コードのブロックでは関係ありません。
このコード ブロックに必要な最終的な目標はminedgeindex
、各スーパーバーテックスのすべての最小エッジを含む正しいベクトルを提供することです。
より明確にし、グラフの背景を無視するために、私は数値の大きなベクトルを持っているだけで、それらを一連のセットに分けます。次に、数値の各セットの最小値を見つけてインデックスを返すためにいくつかの並列スレッドが必要ですそれらの分は、 vector に保存しますminedgeindex
。
さらに明確にする必要がある場合は、私に聞いてください。この作業を手伝ってください。主な問題は、私が正しくやっているかわからないプライベート変数と共有変数の宣言だと思います。
前もって感謝します!