【问题标题】:How much does pointer indirection affect efficiency?指针间接对效率有多大影响?
【发布时间】:2011-12-20 11:37:13
【问题描述】:

解引用指针是否比直接访问该值要慢得多?我想我的问题是 - 遵从运算符有多快?

【问题讨论】:

  • 你关心的是速度还是内存?
  • 您的问题是关于速度还是内存?
  • 一般无法回答。在 L1 缓存中命中的内存访问将比访问实际 RAM 的速度快数百(可能数千)倍。不要猜测;基准测试。
  • 如果您的意思是“直接”,如array[i] 而不是*(ptr),那么没有任何区别。 array[i]*(array+i) 的简写,您可以在现代 CPU 中免费获得 +i
  • 不,我只是想知道指针间接的实际成本是多少

标签: c++ pointers


【解决方案1】:

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

当然,假设变量没有放在寄存器中,在某些情况下,例如紧密循环,它会是这样。我相信这个问题会在没有这种情况的情况下寻求开销的答案。

【讨论】:

    【解决方案2】:

    由于现代 CPU 的工作方式,通过指针间接可能要慢得多。但它与运行时内存无关。

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

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

    缓存发挥作用是因为指针可能指向不在缓存中的内存并且必须获取它。如果预测有效,则将其最小化,但如果无法进行预测,那么在最坏的情况下,您可能会产生双重影响:指针不在缓存中,并且指针目标也不在缓存中。在最坏的情况下,CPU 会停顿两次。

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

    【讨论】:

    • 好的,所以如果我有几个使用缓冲区的嵌套循环(每次使用缓冲区时,它都会在此 fnc 中取消引用指针两次),指针值(大概)是可预测的?总体而言,这并不重要?
    • 如果缓冲区小到足以放入缓存中,那么无论是否可预测,内存访问都会非常快。
    • @user965369:尽你最大的努力确保缓冲区适合 L1 缓存,如果你不能这样做,至少让它适合 L2 缓存。为了最大速度处理缓存大小的块中的更大缓冲区。
    【解决方案3】:

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

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

    最重要的是,它通常可以忽略不计,通常低于您甚至可以可靠测量的阈值。

    【讨论】:

      【解决方案4】:

      取决于以下内容:

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

      也就是说,在不缩小范围的情况下,有太多变量无法进行有用的推测。

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

      【讨论】:

        【解决方案5】:

        它需要更多的内存访问:

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

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

        【讨论】:

        • 它需要更多的内存访问,这在紧密循环中可能是禁止的。并非所有 CPU 操作都是平等的。
        猜你喜欢
        • 2011-10-26
        • 1970-01-01
        • 2013-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-31
        • 2014-02-26
        相关资源
        最近更新 更多