【问题标题】:Error: Expression must be a modifiable lvalue错误:表达式必须是可修改的左值
【发布时间】:2014-03-11 11:08:47
【问题描述】:

当我尝试将值分配给 x_dev、y_dev 和 pearson 时,我在 for 循环中出现了这个错误。据我所知,它们都应该是可修改的。谁能看到我哪里出错了?

class LoopBody
{  
    double *const x_data;
    double *const y_data;
    double const x_mean;
    double const y_mean;  
    double x_dev;
    double y_dev;
    double pearson; 


public:
    LoopBody(double *x, double *y, double xmean, double ymean, double xdev, double ydev, double pear) 
            : x_data(x), y_data(y), x_mean(xmean), y_mean(ymean), x_dev(xdev), y_dev(ydev), pearson(pear) {}  

    void operator() (const blocked_range<size_t> &r) const {              
        for(size_t i = r.begin(); i != r.end(); i++)
        {
            double x_temp = x_data[i] - x_mean;
            double y_temp = y_data[i] - y_mean;

            x_dev += x_temp * x_temp;
            y_dev += y_temp * y_temp;

            pearson += x_temp * y_temp;

        }
    }
};

按照@Bathsheba 的建议,我已经克服了这些问题。然而,当运行 parallel_for 时,操作符会运行,但永远不会进入 for 循环。

这就是我所说的parallel_for:

parallel_for(blocked_range<size_t>(0,n), LoopBody(x, y, x_mean, y_mean, x_dev, y_dev, pearson), auto_partitioner());

【问题讨论】:

    标签: c++ tbb lvalue


    【解决方案1】:

    () 运算符标记为 const,并且您正在尝试修改类成员数据(例如 x_devy_devperson)。这是不允许的,这就是您收到编译时错误的原因。

    您可能希望从方法中删除 const

    或者,您可以将要修改的成员数据标记为mutable,但这不是首选解决方案,因为它会使代码变脆、难以阅读并且可能对多线程造成严重破坏。

    【讨论】:

    • 这解决了这个问题,但我现在在编译时遇到错误:c:\program files (x86)\tbb41\include\tbb\parallel_for.h(110): error C3848: expression has type 'const LoopBody' 将丢失一些 const-volatile 限定符,以便调用 'void LoopBody::operator ()(const tbb::blocked_range &)' 谷歌搜索这表明修复将包括我刚刚删除的 const .
    • 问题是() 不应该修改类成员数据。为什么你需要这样做?如果你真的需要那么,也许,使类成员mutable 并标记函数const 前进的方向。但我不喜欢这样,因为我在答案中陈述了原因。
    • 你是绝对正确的() 不应该修改类成员,特别是因为tbb::parallel_for 使用多个主体实例,并且在单个实例中累积的任何内容都将丢失。因此,constmutable 的组合只会隐藏真正的问题。正确的解决方案是使用tbb::parallel_reduce
    【解决方案2】:

    您似乎想要进行归约,即在数据上计算一些聚合值。

    为此,TBB 提供了一个特殊的函数模板:parallel_reduce。与您现在可能使用的 parallel_for 不同,parallel_reduce 不需要主体类的 operator() 为 const,因为该类的实例会累积部分结果。但是,它对类提出了其他要求:需要有一个特殊的构造函数以及一个方法来合并来自另一个 body 实例的部分结果。

    更多信息可以在英特尔(R) TBB 用户指南中找到:http://www.threadingbuildingblocks.org/docs/help/tbb_userguide/parallel_reduce.htm

    还有parallel_reduce 的重载,它需要两个函子——一个用于主体,另一个用于合并部分结果——以及用于初始化累加器的特殊“身份”值。但是您一次计算三个聚合值,因此您仍然需要有一个结构或类来将所有三个值存储在一个变量中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-15
      • 2015-03-30
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      • 2021-10-02
      • 1970-01-01
      相关资源
      最近更新 更多