2011-11-02 40 views
7

解引用指针是否比直接访问该值要慢?我想我的问题是 - 尊敬操作符有多快?指针间接影响效率多少?

+3

难道你关心的是速度还是记忆? – ruslik

+0

你的速度或记忆问题? –

+1

不可能一般回答。访问L1缓存的内存访问将比访问实际内存的访问速度快数百倍(可能是数千倍)。不要推测;基准。 – Nemo

回答

20

通过指针间接寻址由于现代CPU的工作原理,会慢得多。但它与运行时内存没有太大关系。

相反,速度受预测和缓存的影响。

当指针未被更改或以可预测的方式更改时(例如,循环中增加或减少四),预测很容易。这允许CPU在实际代码执行之前基本上运行,找出指针值将会是什么,并将该地址加载到缓存中。当指针值由像哈希函数这样的复杂表达式构建时,预测变得不可能。

缓存起作用,因为指针可能指向不在缓存中的内存,它将不得不被提取。如果预测有效,这将被最小化,但如果预测不可能,那么在最坏的情况下,您可能会产生双重影响:指针不在缓存中,指针目标也不在缓存中。在最坏的情况下,CPU会停顿两次。

如果指针用于函数指针,则CPU的分支预测器开始工作。在C++虚拟表中,函数值都是恒定的,预测器很容易。当执行通过间接跳转时,CPU将准备好运行代码并在流水线中。但是,如果它是一个不可预知的函数指针,性能影响可能会很大,因为流水线需要刷新,每次跳转会浪费20-40个CPU周期。

+0

好吧,如果我有一对使用缓冲区的嵌套循环(每次它使用缓冲区,它在这个fnc中将指针取消引用两次),指针值将会(presumabley)是可预测的?它不会真的重要吗? – user965369

+2

如果缓冲区足够小以适应缓存,则无论它们是否可预测,内存访问都将非常快。 – Nemo

+0

@ user965369:尽你所能确保缓冲区适合L1缓存,如果你不能这样做,至少可以将它适合L2缓存。为了最大速度处理缓存大小块中较大的缓冲区。 –

2

它需要存储器访问更多:

  1. 读存储到指针变量
  2. 读取该地址处的值读取

这可能不等于2操作简单的地址,因为访问尚未加载到缓存中的地址也可能需要更多时间。

+0

它需要*内存访问*更多,这可能是在一个紧密的循环禁止。并非所有的CPU操作都是相同的。 –

+0

是的..你是对的..我解决了我的回答 – Heisenbug

2

它的确如此。它需要额外的提取。
通过值访问变量,变量直接从其内存位置读取。
通过指针访问相同的内容会增加从指针中获取变量地址的开销,然后从该内存位置读取值。

Ofcourse,假设变量没有放在寄存器中,它会在一些情况下,如紧密循环。我相信这个问题会在假设没有这种情况下寻求间接成本的回答。

3

要看的东西,如:

  • 的“直接访问”值是否在寄存器中已经,或在栈上(这也是一个间接指针)
  • 目标地址是否在缓存中已经
  • 的高速缓存架构,总线架构等

即太多的变量,有效地推测不缩小下来。

如果您真的想知道,请在您的特定硬件上进行基准测试。

2

假设你正在处理一个真正的指针(不是某种智能指针),取消引用操作根本不消耗(数据)内存。它确实(可能)涉及额外的内存引用:一个用于加载指针本身,另一个用于访问指针指向的数据。

但是,如果您在紧密循环中使用指针,它通常会在持续时间内加载到寄存器中。在这种情况下,成本主要是在额外注册压力方面(即,如果您使用寄存器来存储该指针,则不能用它来同时存储其他内容)。如果你有一个算法,否则正好填充寄存器,但注销指针会溢出到内存它可以有所作为。曾经,这是一个非常大的损失,但是对于大多数现代CPU(具有更多寄存器和板载高速缓存),这很少成为一个大问题。明显的例外是嵌入式CPU,寄存器较少,没有缓存(并且没有片上存储器)。

底线是它通常很小,通常低于阈值,甚至可以可靠地进行测量。