2016-04-04 6 views
1

私は、強制的に指示されたグラフレイアウトを計算するアルゴリズムを実装しています。いくつかのループを加速するためにOpenMPディレクティブを追加したいと思います。いくつかのコースを読んだ後、私は私の理解に基づいていくつかのOpenMP指令を追加しました。コードはコンパイルされますが、シーケンシャルバージョンと同じ結果は返されません。OpenMP:whileループ内でループを並列化する

私のコードを見て、私のOpenMPバージョンで何がうまくいかないのか理解するのに十分なほど親切になるのだろうかと思います。

ここにアーカイブをダウンロードしてください:あなたが見たよう http://www.mediafire.com/download/3m42wdiq3v77xbh/drawgraph.zip

、私は並列化するコードの一部は次のとおりです。

unsigned long graphLayout(Graph * graph, double * coords, unsigned long maxiter) 

特に、計算リソースの多くを消費し、これら二つのループ:

/* compute repulsive forces (electrical: f=-C.K^2/|xi-xj|.Uij) */  
    for(int j = 0 ; j < graph->nvtxs ; j++) { 
    if(i == j) continue; 
    double * _xj = _position+j*DIM; 
    double dist = DISTANCE(_xi,_xj);   
    // power used for repulsive force model (standard is 1/r, 1/r^2 works well) 
    // double coef = 0.0; -C*K*K/dist;  // power 1/r 
    double coef = -C*K*K*K/(dist*dist); // power 1/r^2 
    for(int d = 0 ; d < DIM ; d++) force[d] += coef*(_xj[d]-_xi[d])/dist; 
    } 

/* compute attractive forces (spring: f=|xi-xj|^2/K.Uij) */ 
    for(int k = graph->xadj[i] ; k < graph->xadj[i+1] ; k++) { 
    int j = graph->adjncy[k]; /* edge (i,j) */ 
    double * _xj = _position+j*DIM; 
    double dist = DISTANCE(_xi,_xj);    
    double coef = dist*dist/K; 
    for(int d = 0 ; d < DIM ; d++) force[d] += coef*(_xj[d]-_xi[d])/dist; 
    } 

ご協力いただきありがとうございます。

答えて

0

maxmove = nmove;またはenergy += nforce2;を行うときには、例えば、データ競合あなたのコード内のを持っています。任意のマルチスレッドコードでは、アトミックアクセス(#pragma omp atomic read/write/update)を使用するか、そのような変数へのアクセスを明示的に同期させる(クリティカルセクション、ロック)まで、スレッドによって共有される変数に書き込むことはできません。まずOpenMPに関するチュートリアルを読んでください。コードにはさらに問題があります。

if(nmove > maxmove) maxmove = nmove; 

この行はアトミックでも機能しません(これを解決するためには、いわゆる比較交換アトミック操作を使用する必要があります)。ここでのより良い解決策は、各スレッドにローカル最大値を計算させてからグローバル最大値に減らすことです。