为什么在这种情况下为 for 循环使用指针性能更高?

Why is using a pointer for a for loop more performant in this case?

我没有 C/C++ 或相关低级语言的背景,所以我以前从未 运行 接触过指针。我是一名主要使用 C# 工作的游戏开发人员,今天早上我终于决定将代码的一些性能关键部分转移到一个不安全的上下文中(请不要 "don't use unsafe" 回答,因为我在做的时候已经读了很多遍研究,因为它已经让我在某些领域获得了大约 6 倍的性能,到目前为止没有任何问题,而且我喜欢在没有分配的情况下做像反向数组这样的事情的能力)。无论如何,在某些情况下我预计不会有任何差异,甚至可能会降低速度,而且我在现实中节省了很多滴答声(在某些情况下我说的是双倍速度)。这种好处似乎随着迭代次数的增加而减少,我不完全理解。

情况是这样的:

int x = 0;
for(int i = 0; i < 100; i++)
    x++;

平均需要 15 个滴答。

编辑:以下是不安全的代码,尽管我认为这是给定的。

int x = 0, i = 0;
int* i_ptr;
for(i_ptr = &i; *i_ptr < 100; (*i_ptr)++)
    x++;

平均需要大约 7 个刻度。

正如我提到的,我没有低级背景,我今天早上才开始使用指针,至少是直接使用,所以我可能遗漏了很多信息。所以我的第一个问题是——为什么在这种情况下指针的性能更高?它不是一个孤立的实例,当然还有很多其他变量,在与 PC 相关的特定时间点,但我在很多测试中得到的这些结果非常一致。

在我的脑海中,操作是这样的:

没有指针:

指针:

在我看来,在这里使用指针肯定会有更多的开销,但是可以忽略不计。在这种情况下,指针如何始终比直接变量更高效?当然,这些也都在堆栈上,所以据我所知,这与它们最终存储的位置无关。

如前所述,需要注意的是此奖励会随着迭代次数的增加而减少,而且速度非常快。我从以下数据中删除了极端值以考虑背景干扰。

在 1000 次迭代时,它们在 30 到 34 个刻度上是相同的。

在 10000 次迭代时,指针慢了大约 20 个刻度。

最多跳10000000次迭代,指针慢了大概10000个刻度左右

我的假设是减少来自我之前介绍的额外步骤,因为有一个额外的查找,这让我想知道为什么它 更多 性能指针比没有低循环计数。至少,我假设它们或多或少是相同的(我想它们在实践中是相同的,但是与数百万次重复测试相差 8 个刻度对我来说是非常确定的)直到我的非常粗略的阈值发现介于 100 到 1000 次迭代之间。

如果我有点吹毛求疵,或者如果这是一个糟糕的问题,我深表歉意,但我觉得确切地知道幕后发生的事情似乎是有益的。如果不出意外,我认为这很有趣!

一些用户认为测试结果很可能是由于测量不准确造成的,至少在某种程度上看起来是这样。当对一千万个连续测试进行平均时,两者的平均值通常是相等的,尽管在某些情况下,指针的使用会产生额外的滴答声。有趣的是,当作为单个案例进行测试时,使用指针的执行时间始终低于不使用指针的情况。当然,在尝试测试的特定时间点,还有很多其他变量在起作用,这使得进一步追踪这一点变得毫无意义。但结果是我学到了更多关于指针的知识,这是我的主要目标,所以我对测试很满意。