如果某个方法是从动态分配的对象调用的,那么它可以以某种方式内联(编译器优化)

时间:2014-01-11 01:41:18

标签: c++ optimization compiler-construction

如果我有这段代码:

class MyClass;

class Child   
{  
public:   
    void ExecuteChild()   
    {   
       parent->ExecuteParent(); //This function   
    }

MyClass* parent;   
};

class MyClass    
{    
 public:
   MyClass    
{   
   child = newChild();
   chilt->parent = this;    
}

   void ExecuteParent()    
{       
//does something    
} 

Child* child

};

std::vector<MyClass*> objects;
int num = GetRandomNumberBetween5and10();
for(int i = 0; i < num; i++)
{
  objects.push_back(new MyClass());
}

for(int i = 0; i < num; i++)
{
  objects[i]->Execute());
}

在启用了所有优化的现代C ++编译器下,是否有可能将Child :: ExecuteParent()内联?我问这个,因为我在项目中有非常类似的情况现场,我必须知道继续这个设计是否有任何意义。

2 个答案:

答案 0 :(得分:1)

原样,代码无法编译!调用parent->ExecuteParent()时,未定义MyClass。也就是说,如果声明和定义的顺序被整理出来并且函数被适当地定义为inline,则编译器可以内联它们:方法ExecuteParent()和{{1在编译时已知它们不是ExecuteChild()。编译器是否内联函数是另一回事。

答案 1 :(得分:1)

我原则上假设方法调用可以内联,因为编译器确实知道objects[i]的类。 如果真的这样做,我会感到惊讶。

当你拥有所谓的“非常高性能密集点”时,我开始得到一个过早优化的气息,我将其定义为解决性能问题,然后才能确定是否之一。

关于性能问题的关键在于它们是什么让你知道它们在哪里。 他们在你不知情的情况下存放在你的代码中。 有时,尝试解决想象中的性能问题会导致创建性能问题。 更重要的是,从来没有一个(根据我的经验)。

例如,假设您有三个性能问题:

  • 你不知道有50%是
  • B占你怀疑的25%
  • C占你不知道的12.5%

那你的策略是什么?

如果你过早地修复了B,那么你将节省25%,相比没有修复它可以获得1.33倍的速度提升。 你可能会对此感到满意,但是......

如果你遵循我推荐的诊断过程,那并不意味着不修复B. 这意味着首先让指出A的诊断让你感到惊讶。 如果你先修复它,你可以节省50%,这样可以获得2倍的速度增益。

更重要的是,当你再次进行诊断时,它说现在B占50%的时间,而不是25%,所以它不仅告诉你你是对的,修复它会给你另外2倍的速度增益,而不仅仅是1.33倍。因此在修复A和B之后,你的速度提高了4倍。 (当然,如果先修复B然后修复A,你最终会在同一个地方。)

最后,无论你是否猜到C是一个问题而不是一个非常大的问题,现在它是一个很大的问题,因为你已经修复了A和B.现在C需要50%的时间,而不是12.5%,所以修复它会给你另一个 2倍的加速。 所以现在你的速度比开始时快8倍。

这完全是您用于查找您没有预料到的问题的方法的结果。 这些都是钱。 Here's an example of a 730x speedup,通过修复六个问题的连续性,其中一些问题在开始时非常小,但是在一起时,它们累计超过99.8%的时间。

当然,你可以从中吸取教训,避免陷阱并编写更快的代码,我想你可以称之为过早优化:)