我正在努力学习并行化,特别是 OpenMP。我有一个顺序 N 体模拟器,可以完美运行并提供正确的输出,但是当我添加并行 for 时,我所有的 x,y 位置都输出为 -nan。
这个算法中没有竞争条件,并且并行创建了一个隐式障碍,所以如果我没有弄错的话(看起来我是这样),这应该可以工作。
当我在某些阶段输出 new_pos
时,我开始得到像 64.4358358.53 这样的数字。我不明白这样的数字怎么可能存在,更不用说用计算机来表示了。
对于造成这些问题的原因有什么想法吗?
for( int t = 0; t < TOTAL_STEPS; ++t )
{
#pragma omp parallel for num_threads( N )
for( int q = 0; q < N; ++q )
{
forces[q][X] = forces[q][Y] = 0;
for( int k = 0; k < N; ++k )
{
if( q == k ) continue;
x_diff = pos[q][X] - pos[k][X];
y_diff = pos[q][Y] - pos[k][Y];
dist = sqrt( x_diff * x_diff + y_diff * y_diff );
// performing a calculation with a distance this small introduces
// small denominator errors
if( dist > 0.01 )
{
dist_cubed = dist * dist * dist;
forces[q][X] -= 1 / dist_cubed * x_diff;
forces[q][Y] -= 1 / dist_cubed * y_diff;
}
else continue;
}
pos_new[q][X] = pos[q][X] + vel[q][X] * timestep;
pos_new[q][Y] = pos[q][Y] + vel[q][Y] * timestep;
vel_new[q][X] = vel[q][X] + ( forces[q][X] * timestep );
vel_new[q][Y] = vel[q][Y] + ( forces[q][Y] * timestep );
}
for( int i = 0; i < N; ++ i )
{
pos[i] = pos_new[i];
vel[i] = vel_new[i];
}
}
注释:
- 我知道 N 个线程并不是最佳的,但这只是练习的一部分
- 对于原型(prototype)制作,我使用 G = 1 且所有质量 = 1,这就是为什么我的公式可能看起来不正确
最佳答案
正如 Gilles 指出的,解决方案是将局部变量设为私有(private)。
#pragma omp parallel for num_threads ( N ) private( x_diff, y_diff, dist, dist_cubed )
是唯一需要的更改
关于C++ 与 OpenMP 在 N 体模拟器中给出 -not-a-numbers (nan),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40456728/