C 去引用迭代器的性能

C 去引用迭代器的性能,c,performance,pointers,memory,C,Performance,Pointers,Memory,我有3个函数,它们的代码如下,运行800x800次: 下面的每个while循环在iter1==lim之前精确地运行了800次,因此在运行800x800x800(5.12亿)次时测量了持续时间 iter1、iter2和lim是双指针。它们指向一个足够大的向量double sum是一个double局部变量 s1和s2是本地无符号整数,两者都等于800 2.257秒后首次跑步: while ( iter1 < lim ) { sum += *iter1 * *iter2; ++i

我有3个函数,它们的代码如下,运行800x800次:

下面的每个
while
循环在
iter1==lim
之前精确地运行了800次,因此在运行800x800x800(5.12亿)次时测量了持续时间

iter1
iter2
lim
指针。它们指向一个足够大的向量
double

sum
是一个
double
局部变量

s1
s2
是本地
无符号整数
,两者都等于800

2.257秒后首次跑步:

while ( iter1 < lim )
{
    sum += *iter1 * *iter2;
    ++iter1;
    iter2 += s2;
}
while(iter1
在7.364秒内完成第二次跑步:

while ( iter1 < lim )
{
    sum += *iter1 * *iter2;
    iter1 += s1;
    iter2 += s2;
}
while(iter1
第三次跑步时间为1.355秒:

while ( iter1 < lim )
{
    sum += *iter1 * *iter2;
    ++iter1;
    ++iter2;
}
while(iter1
如果我删除
sum+=*iter1**iter2指令,它们都在1.07秒左右运行

如果我删除第二次乘法并将指令更改为
sum+=*iter1,第一次和第三次运行时间为1.33秒,第二次运行时间为1.46秒

如果我移除另一个迭代器,如下所示:
sum+=*iter2,然后第一次和第二次运行约2.2秒,而第三次运行约1.35秒


显然,性能下降与添加到
iter1
iter2
的数量有关。在处理器如何访问内存和取消引用指针方面,我不是专家,因此我希望社区中有人比我了解更多,并愿意为我的问题提供一些帮助

如果您需要关于我运行这些测试的硬件的任何信息,或者任何其他证明有用的信息,请随时在评论中询问

编辑:问题是第二个函数与其他函数相比速度较慢,我想知道我是否可以做些什么使它运行得更快,因为它似乎在做与其他2类似的事情


编辑2:所有度量都是在发布版本中进行的

性能差异与迭代器无关。不同之处在于,以大于单位的步幅通过大量数据时会出现额外的缓存未命中。

这只是数据局部性的一种表现。
在书的下一页看东西比在下一页第800页看东西花费的时间要少。你自己在家试试。

我猜结果是机器代码,这取决于编译器/平台的特性

为了检索指针值,内部机器将使用类似加载指令的东西,让我们调用虚构的汇编代码
LD addr0

addr0
指使用的地址寄存器

许多CPU提供诸如
LD addr0+
之类的语句,在加载存储值后增加地址。通常,这种额外的增量不会导致任何额外的循环

我使用过一些编译器,如果地址增量是由增量操作符直接在解引用语句之后或在解引用语句中完成的,那么它们只能生成
addr0+
语句

因此,最后一个例子可能是最有效的机器代码


如果您能为每个示例发布编译过程的汇编程序代码,那将非常有趣。

“因此我希望社区中的某个人比我了解更多,并愿意对我的问题进行解释”,问题是什么?我不太明白您的“问题”是什么,您尝试了不同的版本,你发现一个更快,所以就用它。。。我遗漏了什么吗?等等,那么你在迭代器中添加了800个,它可以工作了吗?每个块都在做不同的事情,你无法通过这种方式比较性能并获得有意义的结果。(++iter1与iter1+=s1不同,因为s1是800)。您正在测试一个版本,优化的构建吗?如果没有,那么你给我们看的这些数字和观察结果是毫无意义的。当问到性能问题时,应该要求您在问题中指定编译器和构建/优化设置。我查看了Dissasembly my IDE(Visual Studio 2012)生成的,它非常简单,没有做任何额外的事情。我从来没有看到过任何加载指令,所以我猜这是您要求的其他指令。“在下一页查看某个指令比在下一页第800页查看某个指令花费的时间要少”。当我只使用iter的一个函数时,第二个函数的运行速度几乎与其他两个函数一样快,尽管迭代器增加了800。为什么我在每一步添加800个迭代器时会花费这么多时间?性能下降不是应该小于“4倍慢”吗?还是在执行其他操作的同时访问内存?时间的变化是由于延迟,即
*iter1
*iter2
,而不是迭代器上的算术运算。因此,删除迭代器不仅可以减少内存访问的数量,还可以使访问更加统一。这可能为各种优化打开了道路。