【问题标题】:C++ parallel_for errorC++ parallel_for 错误
【发布时间】:2016-07-29 21:45:55
【问题描述】:

我正在尝试学习如何使用 TBB,因此我正在修改我发现的一个示例程序,该程序旨在计算复数数组的幂。最初,它是将一个数组传递到 parallel_for 循环中,但我正在尝试更改它,以便它传入一个向量。但是,我无法编译我的代码;我收到以下错误(使用 g++ -g program_name.cpp -ltbb 编译):

error: passing ‘const std::complex<double>’ as ‘this’ argument
       discards qualifiers [-fpermissive] result[i] = z;

我的代码如下:

#include <cstdlib>
#include <cmath>
#include <complex>
#include <ctime>
#include <iostream>
#include <iomanip>
#include "tbb/tbb.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/parallel_for_each.h"
#include "tbb/task_scheduler_init.h"

using namespace std;
using namespace tbb;
typedef complex<double> dcmplx;

dcmplx random_dcmplx ( void )
{
   double e = 2*M_PI*((double) rand())/RAND_MAX;
   dcmplx c(cos(e),sin(e));
   return c;
}

class ComputePowers
{
   vector<dcmplx>  c; // numbers on input
   int d;           // degree
   vector<dcmplx>  result;  // output
   public:
      ComputePowers(vector<dcmplx> x, int deg, vector<dcmplx> y): c(x), d(deg), result(y) { }

      void operator() ( const blocked_range<size_t>& r ) const
      {
         for(int i=r.begin(); i!=r.end(); ++i)
         {
            dcmplx z(1.0,0.0);
            for(int j=0; j < d; j++) {
                z = z*c[i];
            };
            result[i] = z;
         }
      }
};

int main ( int argc, char *argv[] )
{
   int deg = 100;
   int dim = 10;

   vector<dcmplx> r;
   for(int i=0; i<dim; i++)
     r.push_back(random_dcmplx());

   vector<dcmplx> s(dim);

   task_scheduler_init init(task_scheduler_init::automatic);

   parallel_for(blocked_range<size_t>(0,dim),
                ComputePowers(r,deg,s));
   for(int i=0; i<dim; i++)
       cout << scientific << setprecision(4)
       << "x[" << i << "] = ( " << s[i].real()
       << " , " << s[i].imag() << ")\n";
   return 0;
}

【问题讨论】:

  • 如果您仍然不理解错误,请在您的 operator() 方法中执行 result[I] = z; 。该方法标记为const,您不应修改标记为const的方法中的数据成员。

标签: c++ tbb function-object


【解决方案1】:

您正在尝试修改const-qualified operator() 中的非mutable 成员字段result

解决此差异。

编辑#1:我已经提到了上面的两个关键字。要么:

  1. operator() 中删除const 限定符:

    void operator() ( const blocked_range<size_t>& r ) { ... }
    
  2. 制作resultmutable:

    mutable vector<dcmplx> result;
    

应用(尽管强烈推荐)变体编号后可能会出现其他错误。 1. 2号只是为了完整,只在marginal situations中使用。

确实会导致第一个变体出现错误。这是因为tbb::parallel_for 通过const&amp; 获取Func,所以它只能在你的仿函数上调用const 限定的成员函数。为什么? TBB 不想通过复制大型仿函数来浪费性能(STL 通过值传递它们)。

我不知道这里的常见做法是什么,我从来没有使用过这个库。


编辑#2:您可能缺少的只是result 不是参考:

vector<dcmplx> &result;

现在您可以对其进行修改,即使在 const-qualified operator() 中也是如此。修改之后被破坏的成员是没有意义的。

不要忘记更改构造函数的签名以通过引用传递y


代码中的离题问题:

  • 不包括&lt;vector&gt;标头

  • using namespace bulky_namespace 全局

  • for-loop 中不使用size_t 代替i

  • 也许更多……

【讨论】:

  • 非常感谢您的回复。我是 C++ 新手。我该怎么做?
  • 感谢您的持续回复。这是否意味着没有办法让parallel_for修改向量?
  • @Student 这属于边缘情况mutable 应该可以工作。
  • const 要求的全部要点是在编译时提醒tbb::parallel_for 可能会复制仿函数任意次数,具体取决于实现。声明它mutable 只是绕过提醒:-(。将resultc 声明为引用成员,以便每次 tbb::parallel_for 复制仿函数时都不会复制。否则,将看不到更新在原始result 中,每次复制将花费 O(N) 时间来复制 N 元素向量。
  • 顺便说一句,我强烈建议学习如何通过引用捕获(即[&amp;])和tbb::parallel_for 一起使用C++11 lambda 表达式。这样做会使函子更加更容易编写。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多