使用OpenMP提高n-body程序性能

时间:2018-06-13 12:10:46

标签: c multithreading openmp

我的目标是提高模拟n体问题的代码的性能。

这是计算时间的地方。需要并行化的两个函数是 calculate_forces() * move_bodies()函数,但由于循环控制变量 t 是双重的,我不能在 #pragma omp并行 语句。

t0 = gettime ();
  for (t = 0; t < t_end; t += dt)
    {
      // draw bodies
      show_bodies (window);

      // computation
      calculate_forces ();
      move_bodies ();
    }

  // print out calculation speed every second
  t0 = gettime () - t0;

两个函数 calculate_forces() move_bodies() 与我使用的相应指令是以下内容:

static void
calculate_forces ()
{
  double distance, magnitude, factor, r;
  vector_t direction;
  int i, j;
 #pragma omp parallel private(distance,magnitude,factor,direction)
 {
   #pragma omp for private(i,j)
   for (i = 0; i < n_body - 1; i++)
    {
      for (j = i + 1; j < n_body; j++)
        {
          r = SQR (bodies[i].position.x - bodies[j].position.x) + SQR (bodies[i].position.y - bodies[j].position.y);
          // avoid numerical instabilities
          if (r < EPSILON)
            {
             // this is not how nature works :-)
              r += EPSILON;
            }
          distance = sqrt (r);
          magnitude = (G * bodies[i].mass * bodies[j].mass) / (distance * distance);

          factor = magnitude / distance;
          direction.x = bodies[j].position.x - bodies[i].position.x;
          direction.y = bodies[j].position.y - bodies[i].position.y;

          // +force for body i
        #pragma omp critical
         {
          bodies[i].force.x += factor * direction.x;
          bodies[i].force.y += factor * direction.y;

          // -force for body j 
          bodies[j].force.x -= factor * direction.x;
          bodies[j].force.y -= factor * direction.y;
          }
        }
    }
 }

}
static void
move_bodies ()
{
  vector_t delta_v, delta_p;
  int i;
 #pragma omp parallel private(delta_v,delta_p,i)
 {
 #pragma omp for 
 for (i = 0; i < n_body; i++)
    {
      // calculate delta_v
      delta_v.x = bodies[i].force.x / bodies[i].mass * dt;
      delta_v.y = bodies[i].force.y / bodies[i].mass * dt;

      // calculate delta_p
      delta_p.x = (bodies[i].velocity.x + delta_v.x / 2.0) * dt;
      delta_p.y = (bodies[i].velocity.y + delta_v.y / 2.0) * dt;

      // update body velocity and position
      #pragma omp critical
      {
      bodies[i].velocity.x += delta_v.x;
      bodies[i].velocity.y += delta_v.y;
      bodies[i].position.x += delta_p.x;
      bodies[i].position.y += delta_p.y;
      }
      // reset forces
      bodies[i].force.x = bodies[i].force.y = 0.0;


      if (bounce)
        {
          // bounce on boundaries (i.e. it's more like billard)
          if ((bodies[i].position.x < -body_distance_factor) || (bodies[i].position.x > body_distance_factor))
            bodies[i].velocity.x = -bodies[i].velocity.x;
          if ((bodies[i].position.y < -body_distance_factor) || (bodies[i].position.y > body_distance_factor))
            bodies[i].velocity.y = -bodies[i].velocity.y;
        }
    }
}

在移动体功能中更改了bodies.velocity和bodies.position的值,但我无法使用缩减。

还有一个校验和函数来计算计算的校验和是否等于参考校验和。该功能如下所示:

static unsigned long
checksum()
{
  unsigned long checksum = 0;

  // initialize bodies
  for (int i = 0; i < n_body; i++)
    {
      // random position vector
      checksum += (unsigned long)round(bodies[i].position.x);
      checksum += (unsigned long)round(bodies[i].position.y);
    }

  return checksum;
}

此函数使用先前计算的bodies.position.x和bodies.position.y的值,这些值是在move_bodies函数中计算出来的,因此我在计算那些似乎没有的值时使用了一个关键块的原因得出正确的答案。谁能给我一些关于我哪里出错的见解?提前谢谢。

0 个答案:

没有答案