【问题标题】:Avoiding overhead in thread creation openMP避免线程创建 openMP 的开销
【发布时间】:2016-10-25 19:53:38
【问题描述】:

因此,在我的代码中,有各种函数可以改变各种数组,调用函数的顺序很重要。由于所有函数都被调用了很多次,因此创建和销毁线程已成为很大的开销。 编辑我的问题,因为我可能过度简化了我当前的问题。 一个例子

double ans = 0;
for (int i = 0; i < 4000; i++){
    funcA(a,b,c);
    funcB(a,b,c);
    ans = funcC(a,b,c):
}
prinft(ans);

funcA、funcB 和 func C 在哪里

void funcA (int* a, point b, int* c){
#pragma omp parallel for shared(a,b,c)
    for (int ii = 0; ii < b.y; ii++){
        for (int jj = 0; jj < b.x; jj++){
          \\ alter values of a and c
        }
    }
}

void funcB (int* a, point b, int* c){
#pragma omp parallel for shared(a,b,c)
    for (int ii = 0; ii < b.y; ii++){
        for (int jj = 0; jj < b.x; jj++){
          \\ alter values of a and c
        }
    }
}

double funcC (int* a, pointb, int* c){
    double k = 0;
#pragma omp parallel for shared(a,b,c) reduction(+:k)
    for (int ii = 0; ii < b.y; ii++){
        for (int jj = 0; jj < b.x; jj++){
          \\ alter values of a and c
            k += sqrt(a[ii*jj] + c[ii**jj]);
        }
    }
    return k;
}

有没有办法在所有函数使用的初始 for 循环之前创建一组线程,并且不会不断地被销毁和再次创建,并且在函数调用中仍然保持正确的顺序?

编辑 2:

我正在寻找一种按顺序运行 funcA funB、funcC 的方法。但是这些函数内部有一些代码将使用多个线程。我想要一种在开始时创建线程的方法,然后它们只会用于那些并行部分,所以最后的答案是正确的。有没有办法避免分叉和加入40000次?

【问题讨论】:

  • gcc openmp thread reuse的可能重复
  • 但是你怎么看k这里?如果没有合理合理的用途,很难解释如何处理它......
  • @Gilles 我已经编辑了我的问题以便更好地解释

标签: c multithreading openmp


【解决方案1】:

假设您的代码的其余部分是正确的,以下应该可以按照您希望的方式工作:

#pragma omp parallel shared( a, b, c )
for (int i = 0; i < 4000; i++){
    funcA(a,b,c);
    funcB(a,b,c);
    funcC(a,b,c):
}

现在不同的函数定义如下:

void funcA( int* a, point b, int* c ) {
    #pragma omp for schedule( static )
    for (int ii = 0; ii < b.y; ii++) {
        for (int jj = 0; jj < b.x; jj++) {
          \\ alter values of a and c
        }
    }
}

void funcB( int* a, point b, int* c ) {
    #pragma omp for schedule( static )
    for (int ii = 0; ii < b.y; ii++) {
        for (int jj = 0; jj < b.x; jj++) {
          \\ alter values of a and c
        }
    }
}

void funcC( int* a, point b, int* c ) {
    #pragma omp for schedule( static )
    for (int ii = 0; ii < b.y; ii++) {
        for (int jj = 0; jj < b.x; jj++) {
          \\ alter values of a and c
        }
    }
}

函数内部的这些 OpenMP 指令称为孤立指令,因为它们出现在任何 OpenMP 并行区域之外的代码中。但是,在运行时,任何预先存在的 OpenMP 线程组都会按照您希望的方式使用它们。

此外,我为每个循环添加了schedule( static ) 子句。这不是代码正确性所必需的,但是这可以通过确保每个线程始终处理跨函数和调用的相同索引来提高性能...

【讨论】:

  • 我想补充一点,这是特定于 OpeMP 运行时的。运行时可以由它们支配(例如,如果长时间不使用,则杀死线程)。但是,许多“流行”运行时使线程保持活动状态。
  • 扩展我的问题(我是 openMP 的新手),如果并行循环的功能之一减少了它是否必须移至线程的初始创建?
  • 函数内部的所有局部变量都在parallel区域内声明,因此它们都是private。如果要进行归约,则需要传递变量以将其作为参数存储给函数。此变量将在parallel 的级别上声明为reduction(:)。另一种可能性是从函数返回每个线程的部分缩减结果,并将它们累积到parallel 区域中的reduction(:) 变量中...
  • 我认为您应该提到parallelfor 指令之间的所有内容都由所有线程执行。这与示例无关,但对于任何偏差都很重要。
  • 您还可以考虑折叠一些循环嵌套以创建更多并行性(取决于可能值得的 b.y 有多大)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 2019-02-08
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
相关资源
最近更新 更多