首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用OpenMP从教程中计算Pi算法

使用OpenMP从教程中计算Pi算法
EN

Stack Overflow用户
提问于 2018-11-11 01:01:42
回答 1查看 2.8K关注 0票数 2

我正在学习关于的OpenMP教程,我在第19页上遇到了这个练习。这是一个π计算算法,我不得不并行化:

代码语言:javascript
复制
static long num_steps = 100000;
double step;
void main ()
{
  int i;
  double x, pi
  double sum = 0.0;
  step = 1.0 / (double)num_steps;

  for(i = 0; i < num_steps; i++)
  {
     x = (I + 0.5) * step;
     sum = sum + 4.0 / (1.0 + x*x);
  }

  pi = step * sum;
}

我不能用,到目前为止,#语用并行。我只能用:

代码语言:javascript
复制
#pragma omp parallel {}
omp_get_thread_num();
omp_set_num_threads(int);
omp_get_num_threads();

我的实现如下所示:

代码语言:javascript
复制
#define NUM_STEPS 800

int main(int argc, char **argv)
{
   int num_steps = NUM_STEPS;
   int i;
  double x;
  double pi;
  double step = 1.0 / (double)num_steps;

  double sum[num_steps];

  for(i = 0; i < num_steps; i++)
  {
      sum[i] = 0;
  }

  omp_set_num_threads(num_steps);
  #pragma omp parallel
  {
    x = (omp_get_thread_num() + 0.5) * step;
    sum[omp_get_thread_num()] += 4.0 / (1.0 + x * x);
  }

  double totalSum = 0;

  for(i = 0; i < num_steps; i++)
  {
    totalSum += sum[i];
  }

  pi = step * totalSum;

  printf("Pi: %.5f", pi);
}

通过使用sum数组忽略这个问题(稍后解释它需要为sum值定义一个关键部分,其中包含#杂注omp关键或#杂注omp原子),上面的推进只适用于有限数量的线程(在我的示例中为800个线程),其中串行代码使用100000步。是否只有上述OpenMP命令才能实现这一目的,还是必须使用#语用omp并行处理,这一点在本教程中还没有提到?

非常感谢您的时间,我真的很想掌握C中使用OpenMP的并行化的概念。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-11 05:53:32

您将需要找到一种方法,使您的并行算法在某种程度上独立于线程数。

最简单的方法是做这样的事情:

代码语言:javascript
复制
int tid = omp_get_thread_num();
int n_threads = omp_get_num_threads();

for (int i = tid; i < num_steps; i += n_threads) {
    // ...
}

这样,无论线程数量多少,工作都会被分割到所有线程上。

如果有3个线程和9个步骤:

  • 线程0将执行步骤0、3、6。
  • 线程1将执行步骤1、4、7。
  • 线程2将执行步骤2、5、8。

这是可行的,但如果每个线程都从某个共享数组访问数据,这并不理想。为了局部性的目的,线程访问附近的数据段会更好。

在这种情况下,您可以将步骤数除以线程数,并给每个线程一个连续的任务集,如下所示:

代码语言:javascript
复制
int tid = omp_get_thread_num();
int n_threads = omp_get_num_threads();

int steps_per_thread = num_steps / n_threads;
int start = tid * steps_per_thread;
int end = start + steps_per_thread;

for (int i = start; i < end; i++) {
    // ...
}

现在,执行9个步骤的3个线程如下所示:

  • 线程0执行步骤0、1、2。
  • 线程1执行步骤3、4、5。
  • 线程2执行步骤6、7、8

这种方法实际上是使用#pragma omp for时最有可能发生的情况。在大多数情况下,编译器只是根据线程数来划分任务,并为每个线程分配一个节。

因此,给定一组2个线程和100次循环迭代,编译器可能会给线程0提供0-49的迭代,对线程1进行迭代( 50-99 )。

注意,如果迭代的次数没有被线程数平均除以,那么剩余的部分需要显式地处理。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53244922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档