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);
}
なぜロックを使用していますか?代わりに 'reduce(+:ax、ay)'を宣言してください。これははるかに良いはずです(しかし、私はあなたの問題を修正することはできません。 – Gilles
OpenMPを使用しているときにエラーを表示する[mcve]を提供できますか? – Zulan
あなたは何を得て、何を期待していますか?私は間違った値を正しいものとどう比較するのですか? – Harald