【问题标题】:Reducing non-static member function overhead减少非静态成员函数开销
【发布时间】:2019-05-03 23:25:25
【问题描述】:

我有一个计算物理代码(有限差分),它对大型数据数组(解决方案字段和系数字段)执行操作(导数)。 系数数据存储为具有重载() 运算符的Model 对象数组。 以下课程是我正在尝试做的一个示例:

class Model
{
public: 
    inline double operator () (double field)
    {
        return alpha*field;
    }
private:
double alpha ;
}

应用程序将使用 Models 的数组:

std::vector<Model> models; // array of models
std::vector<double> input;
std::vector<double> output;
...    
for (int i = 0; i < models.size(); i++)
{
    output[i] = models[i](input[i]);
} 

问题是使用() 运算符会产生很大的开销。

我已经按原样分析了代码,然后又删除了() 运算符并内联编写了代码。 (我使用的是 g++ 7.3.0.,在 Ubuntu 18.04 上运行)。我正在使用-Winline 进行编译,而 g++ 并没有抱怨它不能内联函数。

我还尝试使用static 函数代替() 运算符,并且没有相同的开销。不幸的是,静态函数无法访问成员变量。其他帖子表明这应该不是问题(例如C++ Non-static member functions overhead),但它似乎确实在这里。

所以我的问题是:这个非静态成员函数的开销来自哪里?

【问题讨论】:

  • 您使用什么级别的优化?此代码与手动内联的代码在时间上的差异有多大?
  • ... 在这个级别上,std::hardware_destructive_interference_size 可能会有所作为。编辑:我没有做过很多次,但是 - 避免缓存线冲突 - 它通常会更快。
  • 你看生成的代码了吗?您使用了哪些编译器选项?
  • 我查看了使用完全优化生成的代码,operator() 调用没有没有开销,因为它是内联的。您使用的是什么编译器和选项?

标签: c++ performance inlining


【解决方案1】:

静态和非静态的区别在于this 指针。代码在所有实例之间共享,但函数有一个隐式参数来访问类的成员。因此,没有像您提到的问题那样的内存开销,但是由于this 的传递以及访问成员变量的指针取消引用,时间成本很小。您可以检查生成的程序集文件以确保它是内联的。

加快执行速度的建议:

  • 使用编译器优化
  • 使用并行:C++ 线程或 OpenMP 是这里的简单选择
  • 更改您的设计以使用 alpha 向量并删除该类,然后您也许可以使用 SIMD

【讨论】:

  • 我知道区别。指针取消引用不太可能是问题所在。在测试手动内联代码时,我添加了一个额外的取消引用以查看这是否是问题 - 没有变化。关于速度:我已经使用了编译器优化以及 MPI、OpenMP 和 Cuda。最后,更改向量结构不是一种选择,因为这需要重新设计完整的代码。
  • 取决于指针是否引用了本地缓存中的内存。访问缓存之外的数据会带来巨大的损失。我知道并且可以尝试的唯一其他微优化是 nothrow()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2014-04-14
  • 2011-01-27
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多