【问题标题】:Optimizing away function calls优化远离函数调用
【发布时间】:2017-05-30 00:01:22
【问题描述】:

是否可以想象 C++ 编译器会优化对只设置类变量的类成员函数的函数调用?示例:

class A
{
    private:
        int foo;
    public:
        void bar(int foo_in)
        {
             foo = foo_in;
        }
}

如果我这样做了

A test;
A.bar(5);

编译器能否对其进行优化以直接访问该成员并将其设置为这样?

【问题讨论】:

  • 开启优化并查看生成的程序集。如果更现代的主要编译器之一这样做,其他编译器也会这样做。
  • 它可以,你甚至可以通过在方法中添加一个“内联”说明符来暗示你强烈希望它,如果它在你的示例中默认没有它。
  • @chris 有趣的是,我通过创建一个成员函数来设置变量和一个成员函数来获取它,然后我设置它并执行 cout << [get member] 并将其优化为 cout << 5跨度>

标签: c++ optimization


【解决方案1】:

是的,它被称为内联。

此外,c++ 专门设计用于支持或使编译器更容易执行非常复杂的继承案例和模板中的此类优化。

有些人会说这是c++ 与其他语言相比非常独特的壮举。它的“高级”功能(主要是指通用编程 - 模板)在设计时就考虑到了这种优化。这也是它在性能方面被认为是高效的原因之一。

这也是为什么我希望在使用任何有信誉的编译器的 inlines 上找到一份体面的工作。

根据我的阅读,这也是为什么很难获得其他高级语言的所有花哨的东西,例如反射机制,或者其他已知的东西。 Java或python。这是因为c++ 被设计为可以轻松内联几乎所有可能的内容,因此很难内省优化代码。

编辑:

因为你说你正在编写一个 OpenGL 的东西,其中 setter 和 getter 的性能以及此类优化很重要,所以我决定详细说明一下,并展示一个更有趣的例子,你可以依赖内联机制。

您可以编写一些接口,避免使用virtual 机制,而是使用模板。例如:

//This is a stripped down interface for matrices for physical objects
//that have Hamiltonian and you can apply external field and temperature to it
template< class Object >
class Iface {
protected:  
    Object& t;

public:
  Iface(Object& obj) : t(obj) {};

  Vector get_eigen_vals() {return t.get_eigen_vals(); };
  Matrix get_eigen_vectors() {return t.get_eigen_vectors(); };

  void set_H(VectorD vect) { t.set_H(vect); };
  void set_temp(double temp)   {t.set_temp(temp);};
};

如果你这样声明接口,你可以用这个接口对象包装一个对象,并将这个接口类的实例传递给你的函数/算法,并且仍然内联所有内容,因为它适用于Object的引用。好的编译器会优化整个Iface

【讨论】:

  • 谢谢,我知道内联,但我不确定在这些情况下它是否会自动执行。这样做非常酷,因为我目前正在编写一个程序,该程序使用具有许多类似功能的类(只是获取或设置变量),而且它不会经历整个函数调用过程,这在性能方面是很好的.
  • @mebob 函数中直接定义的函数隐含为inline,因此您可以期望编译器会做出一定的努力以内联方式生成它们。
  • @drescherjm 我同意它通常可以忽略不计,但我正在使用 OpenGL 编写一个 3D 程序,并且将不断访问包含变换矩阵等每一帧的类。
  • @mebob 完全理解。我过去也做过类似的事情(在我的整个职业生涯中都参与了医学成像)。
  • @luk32 内联它们的原因是编译器决定内联它们。它们是内联函数的原因(编译器应该强烈暗示它们应该被内联)是因为标准是这样说的。
【解决方案2】:

比内联更笼统地回答这个问题:

标准中有一些东西被称为 as-if 规则。它表示允许编译器对您的程序进行任何更改,只要它不影响可观察的行为。甚至有一些例外情况允许他们改变技术上确实会改变可观察行为的事物。

它可以省略函数调用甚至完整的类。只要不破坏任何东西,它基本上可以为所欲为。

【讨论】:

    【解决方案3】:

    是的,编译器可以优化这个调用。 这实际上是非常简单的内联案例。 允许编译器做更多的事情(它可以展开循环,优化局部变量,用常量替换计算等)

    【讨论】:

      猜你喜欢
      • 2014-01-13
      • 1970-01-01
      • 2021-02-13
      • 2011-08-30
      • 2012-09-27
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多