在成员函数中循环内部的std :: vector c ++ size()的性能

pet*_*sev 2 c++ stl vector compiler-optimization

类似的问题,但不太具体: 循环中vector :: size()的性能问题

假设我们在一个成员函数中:

void  Object::DoStuff()  {

   for( int k = 0; k < (int)this->m_Array.size(); k++ )
   {  
       this->SomeNotConstFunction();
       this->ConstFunction();

       double x = SomeExternalFunction(i);
   }
}
Run Code Online (Sandbox Code Playgroud)

1)我愿意相信,如果仅调用"SomeExternalFunction",编译器将优化而不是冗余地调用m_Array上的size()......是这种情况吗?

2)你几乎肯定不会从速度上提高速度

  int N = m_Array.size()
  for( int k = 0; k < N; k++ ) { ... } 
Run Code Online (Sandbox Code Playgroud)

如果你正在调用一些非const的成员函数?

编辑不确定这些关于微优化的低票和讽刺评论来自哪里,或许我可以澄清一下:

首先,它不是要优化本身,而是要了解编译器将要修复的内容.通常我使用size()函数,但我现在问,因为这里数组可能有数百万个数据点.

其次,情况是"SomeNotConstFunction"可能极有可能改变数组的大小,或者它的能力可能取决于其他一些被切换的变量.所以,我问的是编译器会在什么时候失败,以及当数组确实可能发生变化时size()的时间成本到底是多少,尽管人为已知的原因不会?

第三,循环中的操作非常简单,只有数百万,但它们是令人尴尬的并行.我希望通过外部放置值可以让编译器矢量化一些工作.

小智 9

不要养成这样做的习惯.

您在(2)中进行优化的情况是:

  • 安全
  • 有明显的区别
  • 你的编译器无法自己解决的问题

很少,而且介于两者之间.

如果只是后两点,我只是建议你担心一些不重要的事情.然而,第一点是真正的杀手锏:你不是想在给自己额外的机会犯错误的习惯来获得.加速缓慢,正确的代码比调试快速,错误的代码要容易得多.

现在,那说,我会尝试回答你的问题.的函数的定义SomeNotConstFunctionSomeConstFunction是(推测)在相同的翻译单元.因此,如果这些函数确实不修改向量,编译器可以解决它,它只会"调用" size一次.

但是,编译器无法访问定义SomeExternalFunction,因此必须假设每次调用该函数都有可能修改向量.循环中存在该函数可确保每次都调用"大小".

然而,我把"被叫"放在引号中,因为它是如此微不足道的功能,它几乎肯定会被内联.此外,该功能非常便宜 - 两个内存查找(几乎都保证是高速缓存命中),以及减法和右移,或者甚至可以执行两者的专用单个指令.

即使SomeExternalFunction什么都不做,size每次"调用"很可能只是循环运行时间的一小部分甚至可以忽略不计.

编辑:响应编辑....

what exactly is the time cost incurred by size() when the array really might change
Run Code Online (Sandbox Code Playgroud)

您在计算两个不同版本的代码时所看到的时间差异.如果你正在做这样的非常低级别的优化,你就无法通过"纯粹的理由"得到答案 - 你必须凭经验测试结果.

如果你真的在做这样的低级别的优化(你可以保证矢量不会调整),你应该更担心的事实,编译器不知道数组的基指针是恒定的,而不是它不知道大小是不变的.

如果SomeExternalFunction真的是编译单元的外部,那么无论你做什么,你几乎都没有机会对编译器进行矢量化.(我想有可能在链接时,虽然....),它也不可能是"小巫见大巫",因为它需要函数调用的开销-至少是"小巫见大巫"对你意味着同样的事情在我身上.(再次,我不知道链接时间优化有多好......)

如果真能保证一些操作不会调整的载体,你可能会考虑优化类的API(或者至少是protectedprivate部分),使其具备自我显然不会调整的载体功能.