2016-11-28 4 views
1

私はOpenMPを使用して順次プログラムを並列プログラムに変換するn-bodyの割り当てに取り組んでいます。 OpenMPをオフにしてもうまく動作するが、それ以外の場合は正しくない結果が出る以下の関数があります。ループ内で宣言されていないループ内で更新される唯一の変数の周りにロックがあります。私は長い間それを凝視してきましたが、私は何が間違っているのか分かりません。どんなヒントも大歓迎です。cの連続をOpenMPの問題に変換する

void update() { 
    int i, j; 
    Body *tmp; 

    omp_lock_t lock; 
    omp_init_lock(&lock); 

    for (i=0; i<numBodies; i++) { 
    double x = bodies[i].x; 
    double y = bodies[i].y; 
    double vx = bodies[i].vx; 
    double vy = bodies[i].vy; 
    double ax = 0; 
    double ay = 0; 

    #pragma omp parallel for num_threads(4) 
    for (j=0; j<numBodies; j++) { 
     double r, mass, dx, dy, r_squared, acceleration; 

     if (j==i) continue; 
     dx = bodies[j].x - x; 
     dy = bodies[j].y - y; 
     mass = bodies[j].mass; 
     r_squared = dx*dx + dy*dy; 
     if (r_squared != 0) { 
     r = sqrt(r_squared); 
     if (r != 0) { 
      acceleration = K*mass/(r_squared); 
      omp_set_lock(&lock); 
      ax += acceleration*dx/r; 
      ay += acceleration*dy/r; 
      omp_unset_lock(&lock); 
     } 
     } 
    } 
    x += vx; 
    y += vy; 
    if (x>=x_max || x<x_min) x=x+(ceil((x_max-x)/univ_x)-1)*univ_x; 
    if (y>=y_max || y<y_min) y=y+(ceil((y_max-y)/univ_y)-1)*univ_y; 
    vx += ax; 
    vy += ay; 
    assert(!(isnan(x) || isnan(y))); 
    assert(!(isnan(vx) || isnan(vy))); 
    bodies_new[i].x = x; 
    bodies_new[i].y = y; 
    bodies_new[i].vx = vx; 
    bodies_new[i].vy = vy; 
    } 
    tmp = bodies; 
    bodies = bodies_new; 
    bodies_new = tmp; 
    omp_destroy_lock(&lock); 
} 
+1

なぜロックを使用していますか?代わりに 'reduce(+:ax、ay)'を宣言してください。これははるかに良いはずです(しかし、私はあなたの問題を修正することはできません。 – Gilles

+0

OpenMPを使用しているときにエラーを表示する[mcve]を提供できますか? – Zulan

+0

あなたは何を得て、何を期待していますか?私は間違った値を正しいものとどう比較するのですか? – Harald

答えて

0

プラグマを外側のループに移動し、削除を削除し、Iとjをプライベートとして追加しました。

関連する問題