【问题标题】:OpenMP Parallelize code inside a for loopOpenMP 在 for 循环中并行化代码
【发布时间】:2018-07-17 21:53:37
【问题描述】:

我想使用 OpenMP 在 for 循环中并行化任务。但是,我不想使用#pragma omp parallel for,因为 (i+1)th 迭代的结果取决于 (i)th 迭代的输出。我试图在代码中生成线程,但是每次创建和销毁它们的时间都非常长。我的代码的抽象描述是:

int a_old=1;
int b_old=1;
int c_old=1;
int d_old=1;
for (int i=0; i<1000; i++)
{
   a_new = fun(a_old);  //fun() depends only on the value of the argument
   a_old = a_new;

   b_new = fun(b_old);
   b_old = b_new;

   c_new = fun(c_old);
   c_old = c_new;

   d_new = fun(d_old);
   d_old = d_new;
}

我如何有效地在每次迭代中使用线程并行计算a_new, b_new, c_new, d_new 的新值?

【问题讨论】:

  • 假设 a、b、c 和 d 相互独立,您可以有 4 个不同的线程,每个变量运行自己的 for 循环

标签: c parallel-processing openmp


【解决方案1】:

只是不要并行化 for 循环内的代码 - 将并行区域移到外部。这减少了线程创建和工作共享开销。然后就可以轻松应用 OpenMP sections

int a_old=1;
int b_old=1;
int c_old=1;
int d_old=1;
#pragma omp parallel sections
{
   #pragma omp section
   for (int i=0; i<1000; i++) {
       a_new = fun(a_old);  //fun() depends only on the value of the argument
       a_old = a_new;
   }
   #pragma omp section
   for (int i=0; i<1000; i++) {
      b_new = fun(b_old);
      b_old = b_new;
   }
   #pragma omp section
   for (int i=0; i<1000; i++) {
      c_new = fun(c_old);
      c_old = c_new;
   }
   #pragma omp section
   for (int i=0; i<1000; i++) {
       d_new = fun(d_old);
       d_old = d_new;
   }
}

还有一个简化:

int value[4];
#pragma omp parallel for
for (int abcd = 0; abcd < 4; abcd++) {
    for (int i=0; i<1000; i++) {
        value[abcd] = fun(value[abcd]);
    }
}

在任何一种情况下,如果fun 执行得相当快,您可能需要考虑在值之间添加填充以避免错误共享。

【讨论】:

  • 非常感谢您的帮助。我尝试了您的解决方案并给了我很好的结果。我现在看到的唯一问题是 fun() 不需要太多时间,因此对于小工作量来说,这可能是一种矫枉过正。非常感谢!
【解决方案2】:

这很简单,正如@kbr 在 cmets 中提到的,每个计算 a、b、c 和 d 都是独立的,因此您可以将它们分离到不同的线程并将相应的值作为参数传递。示例代码如下所示。

#include<stdio.h>
#include <pthread.h>

void *thread_func(int *i)
{
    for (int j=0; j<1000; j++)
    {
        //Instead of increment u can call whichever function you want here.
        (*i)++;
    }
}

int main()
{
    int a_old=1;
    int b_old=1;
    int c_old=1;
    int d_old=1;
    pthread_t thread[4];

    pthread_create(&thread[0],0,thread_func,&a_old);
    pthread_create(&thread[1],0,thread_func,&b_old);
    pthread_create(&thread[2],0,thread_func,&c_old);
    pthread_create(&thread[3],0,thread_func,&d_old);

    pthread_join(&thread[0],NULL);
    pthread_join(&thread[1],NULL);
    pthread_join(&thread[2],NULL);
    pthread_join(&thread[3],NULL);

    printf("a_old %d",a_old);
    printf("b_old %d",b_old);
    printf("c_old %d",c_old);
    printf("d_old %d",d_old);

}

【讨论】:

  • yadhu,我认为 OP 想要明确地使用 OpenMP(可能是因为它的设计是为了尽量减少对现有代码的必要更改,我只是在推测)。使用 pthreads 似乎是一种合适的方式,但似乎不是 OP 所要求的。
  • Battu,请评论这是否对您的需要有帮助。
  • 非常感谢您的帮助。这是使用 pthread 的有效解决方案。但是,我正在研究一种更独立于平台的解决方案。如果支持 OpenMP,那么我们可以加速这部分。如果没有,我们必须以串行方式进行。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2021-10-18
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多