C++ 使用OpenMP优化外环并减少

C++ 使用OpenMP优化外环并减少,c++,c++11,parallel-processing,openmp,C++,C++11,Parallel Processing,Openmp,我对函数有点纠结。如果我尝试用一个 #pragma omp parallel reduction(+:det). 有人能告诉我如何解决它以及为什么它失败了吗 // template<class T> using vector2D = std::vector<std::vector<T>>; float Det(vector2DF &a, int n) { vector2DF m(n - 1, vector1DF(n - 1, 0));

我对函数有点纠结。如果我尝试用一个

#pragma omp parallel reduction(+:det). 
有人能告诉我如何解决它以及为什么它失败了吗

// template<class T> using vector2D = std::vector<std::vector<T>>;

float Det(vector2DF &a, int n)
{
  vector2DF m(n - 1, vector1DF(n - 1, 0));

  if (n == 1) return a[0][0];
  if (n == 2) return a[0][0] * a[1][1] - a[1][0] * a[0][1];

  float det = 0;
  for (int i = 0; i < n; i++)
  {
    int l = 0;
#pragma omp parallel for private(l)
    for (int j = 1; j < n; j++)
    {
      l = 0;
      for (int k = 0; k < n; k++)
      {
        if (k == i) continue;
        m[j - 1][l] = a[j][k];
        l++;
      }
    }
    det += std::pow(-1.0, 1.0 + i + 1.0) * a[0][i] * Det(m, n - 1);
  }

  return det;
}
//使用vector2D=std::vector的模板;
浮点数(矢量2DF&a,整数n)
{
向量2DFM(n-1,向量1DF(n-1,0));
如果(n==1)返回[0][0];
如果(n==2)返回a[0][0]*a[1][1]-a[1][0]*a[0][1];
浮点数=0;
对于(int i=0;i
如果并行化外部循环,则该行上存在竞争条件:

m[j - 1][l] = a[j][k];
另外,您可能需要一个
并行简化
,而不仅仅是
并行简化

问题是,
m
是共享的,即使考虑到它在内部循环中被完全覆盖,也没有必要这样做。始终尽可能在本地声明变量,这样可以避免错误共享变量的问题,例如:

float Det(vector2DF &a, int n)
{
  if (n == 1) return a[0][0];
  if (n == 2) return a[0][0] * a[1][1] - a[1][0] * a[0][1];

  float det = 0;
  #pragma omp parallel reduction(+:det)
  for (int i = 0; i < n; i++)
  {
    vector2DF m(n - 1, vector1DF(n - 1, 0));
    for (int j = 1; j < n; j++)
    {
      int l = 0;
      for (int k = 0; k < n; k++)
      {
        if (k == i) continue;
        m[j - 1][l] = a[j][k];
        l++;
      }
    }
    det += std::pow(-1.0, 1.0 + i + 1.0) * a[0][i] * Det(m, n - 1);
  }
  return det;
}
现在,您也可以将
m
声明为
firstprivate
,但这将假定复制构造函数生成一个完全独立的深度副本,从而使代码更难以推理


请注意,您应该始终包括预期输出、实际输出和a。

如果您并行化外部循环,则此行存在竞争条件:

m[j - 1][l] = a[j][k];
另外,您可能需要一个
并行简化
,而不仅仅是
并行简化

问题是,
m
是共享的,即使考虑到它在内部循环中被完全覆盖,也没有必要这样做。始终尽可能在本地声明变量,这样可以避免错误共享变量的问题,例如:

float Det(vector2DF &a, int n)
{
  if (n == 1) return a[0][0];
  if (n == 2) return a[0][0] * a[1][1] - a[1][0] * a[0][1];

  float det = 0;
  #pragma omp parallel reduction(+:det)
  for (int i = 0; i < n; i++)
  {
    vector2DF m(n - 1, vector1DF(n - 1, 0));
    for (int j = 1; j < n; j++)
    {
      int l = 0;
      for (int k = 0; k < n; k++)
      {
        if (k == i) continue;
        m[j - 1][l] = a[j][k];
        l++;
      }
    }
    det += std::pow(-1.0, 1.0 + i + 1.0) * a[0][i] * Det(m, n - 1);
  }
  return det;
}
现在,您也可以将
m
声明为
firstprivate
,但这将假定复制构造函数生成一个完全独立的深度副本,从而使代码更难以推理


请注意,您应该始终包括预期输出、实际输出和a。

计算错误,预期输出是什么?实际产量是多少?您采取了哪些步骤尝试自己解决问题?这是原始版本:/回答您的问题(或解决您的问题)所需的所有信息都应该出现在问题本身中,而不是一些可能在未指定时间过期的外部链接中。出于这个原因-我拒绝关注外部链接。不要写
std::pow(-1.0,1.0+I+1.0)*…
,这与
std::pow(-1.0,I)*…
相同。使用类似于
(i%2==0?1.0:-1.0)*……
的方法执行此操作,或者即使如此:
(i%2==0?det+=…:det-=…)
。计算错误,预期输出是什么?实际产量是多少?您采取了哪些步骤尝试自己解决问题?这是原始版本:/回答您的问题(或解决您的问题)所需的所有信息都应该出现在问题本身中,而不是一些可能在未指定时间过期的外部链接中。出于这个原因-我拒绝关注外部链接。不要写
std::pow(-1.0,1.0+I+1.0)*…
,这与
std::pow(-1.0,I)*…
相同。使用类似于
(i%2==0?1.0:-1.0)*……
的方法来实现这一点,甚至是这样:
(i%2==0?det+=…:det-=…)