【问题标题】:Threads fighting over global variables in class using OpenMP task使用 OpenMP 任务在类中争夺全局变量的线程
【发布时间】:2021-12-26 16:19:28
【问题描述】:

我目前正在尝试使用 OpenMP 找出大小为 k 的集团是否存在于无向图中,以使代码运行得更快。

这是我要并行化的代码:

bool Graf::doesCliqueSizeKExistParallel(int k) {
  if (k > n) return false;
  clique_parallel.resize(k);
  bool foundClique = false;

  #pragma omp parallel
  #pragma omp single
  for (int i = 0; i < n; i++) {
     if (degree[i] >= k - 1) {
      clique_parallel[0] = i;

      #pragma omp task
      doesCliqueSizeKExistParallelRecursive(i + 1, 1, k, foundClique);
  }
}

return foundClique;
}

void Graf::doesCliqueSizeKExistParallelRecursive(int node, int currentLength, int k, bool & foundClique) {
   for (int j(node); j < n; j++) {
   if (degree[j] >= k - 1) {
     clique_parallel[currentLength - 1] = j;
     bool isClique=true;
     for(int i(0);i<currentLength;i++){
       for(int l(i+1);l<currentLength;l++){
        if(!neighbors[clique_parallel[i]][clique_parallel[l]]){isClique=false; break;}
       }
       if(!isClique) break;
     }
     if (isClique) {
       if (currentLength < k)
      doesCliqueSizeKExistParallelRecursive(j + 1, currentLength + 1, k, foundClique);
     else {
      foundClique= true;
      return;
     }
   }
  }
 }

}

这里的问题,我想可能是这种情况是变量degreeneighborsclique_parallel 都是全局的,当某个线程试图写入其中一个变量时,另一个变量来了写入该变量而不是正确的线程。我尝试的唯一解决方案是将这三个变量作为副本传递给函数,以便每个线程都有自己的变量,但它不起作用。我试图不使用#pragma omp taskwait,因为那只是顺序算法,不会有任何加速。目前我迷路了,不知道如何解决这个问题(如果它是一个问题),不知道还有什么可以尝试或如何避免在线程之间共享这些变量。

这里是班级Graf

  class Graf {
  int n; // number of nodes
  vector<vector<int>> neighbors; //matrix adjacency
  vector<int> degree; //number of nodes each node is adjacent to
  vector<int> clique_parallel;
  bool directGraph;
  void doesCliqueSizeKExistParallelRecursive(int node, int currentLength, int k, bool & foundClique);
  public:
  Graf(int n, bool directGraph = false);
  void addEdge(int i, int j);
  void printGraf();
  bool doesCliqueSizeKExistParallel(int k);

};

所以我的问题是,在这段代码中,线程正在争夺全局变量的问题,还是其他原因?任何帮助都是有用的,如果您对代码有任何疑问,我会回答。

【问题讨论】:

    标签: c++ parallel-processing openmp


    【解决方案1】:

    您观察到omp task wait 将其转换为顺序算法是正确的。实际上更糟糕的是:它将您的深度优先搜索算法变成了有效的广度优先算法,它将遍历整个空间。

    好的。首先使用task group,它在生成任务的for循环结束时有一个隐式任务等待。

    接下来,让您的任务返回 false 或找到的集团的值。

    现在有一个大技巧:一旦一个任务找到了解决方案,调用omp cancel task group,这会让你离开for循环,你可以保留你找到的值!此取消将终止该级别的所有其他任务(及其递归生成的任务)。现在递归的魔力开始发挥作用,所有组都在树的更高处被取消。

    我曾经为另一个递归搜索问题解决了这个问题,但我相信您可以将其转化为您的问题:https://pages.tacc.utexas.edu/~eijkhout/pcse/html/omp-examples.html#Treetraversal

    【讨论】:

    • 我听取了您的建议,算法现在可以完美运行,但现在唯一的问题是,即使我添加了#pragma omp cancel taskgroup,它也不会取消 for 循环。这是新代码:pastebin.com/Hie3CRq1
    • 你有没有抓住需要设置环境变量OMP_CANCELLATION=true的语句?我不知道为什么默认情况下这是错误的。
    • 是的,我设置了OMP_CANCELLATION=true,这是证明ibb.co/C79xDV7
    • 为什么你认为它没有取消?
    • 您使用哪个编译器?是否支持任务取消?
    猜你喜欢
    • 2011-01-07
    • 2013-11-16
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多