c ++通过引用传递值与通过POD副本传递值

时间:2017-09-08 19:36:49

标签: c++ optimization

我听说通过引用传递变量并不总是比传递值更快。对于大变量,通过引用传递更快,但对于小变量,这个问题可能很棘手。

按值传递需要时间来创建副本,但是获取局部变量的值应该更快。 通过引用传递不会浪费时间来创建变量副本,但是查看指针然后查看所需的数据。

我知道这个细节在优化问题上并不那么重要但是我测量它很有意思(我知道-O0是优化的但是这个代码很简单,经过优化我不知道我是什么正在测量)

g ++ -std = c ++ 14 -O0 -g3 -DSIZE_OF_DATA_ARRAY = 16 main.cpp&& ./a.out

g ++(Ubuntu 6.3.0-12ubuntu2)6.3.0 20170406

  • SIZE_OF_DATA_ARRAY |复制时间[s] |参考时间[s]
  • 4 | 0.04 | 0.045
  • 8 | 0.04 | 0.46
  • 16 | 0.04 | 0.05
  • 17 | 0.07 | 0.05
  • 24 | 0.07 | 0.05

我的问题:

  1. 为什么复制与结构大小的执行时间相当恒定?

  2. 为什么复制时有16到17之间的阈值?

  3. 猜猜:它与缓存连接

    我的代码:

    {{1}}

1 个答案:

答案 0 :(得分:0)

  

为什么复制与结构大小的执行时间相当恒定?

最好的理解是查看汇编语言以查看编译器发出的指令。这里的优化取决于编译器的优化设置以及您是处于发布还是调试配置。

还取决于处理器。例如,某些处理器可能具有用于复制大块存储器的专用指令。其他处理器可以以并行块的形式复制数据,具体取决于结构的大小。此外,某些平台可能具有硬件辅助,例如DMA控制器。

唉,有时展开可能比使用特殊指令或硬件协助(取决于数据大小)更快。

  

为什么复制时有16到17之间的阈值?

阈值可以在对齐边界和非对齐之间。

我们来看一个32位处理器。它喜欢一次访问(获取)4个字节。访问24个字节需要6次提取。访问16个字节需要4次读取 但是,访问17,18或19个字节需要5次提取。它可以获取另外4个字节来获得剩余的字节。

另一种情况是复制功能的实现。某些复制功能可能使用32位副本作为第一组4字节数量,然后切换到字节比较剩余部分。它可以切换到所有字节的字节复制,具体取决于数据的大小。很多可能性。

系统的真实性在于调试汇编语言或复制数据的功能。

缓存命中率&未命中
您的性能指标可能会受到处理器缓存操作的影响。如果处理器将数据放在缓存中,则循环速度会快得多。通常,首次访问数据会受到性能影响。如果您的数据对于缓存而言太大或者位于数据缓存大小的域之外,则可能会浪费更多时间重新加载数据缓存。

指令缓存问题
许多处理器都有大型管道和数据指令缓存。当他们遇到分支(例如for循环结束)时,处理器可能必须重置指令缓存并从程序中的另一个位置重新加载。这需要时间。您可以通过以不同大小的块展开循环并测量性能来演示。