取消引用迭代器性能

时间:2015-07-08 13:18:49

标签: c performance pointers memory

我有3个函数可以归结为下面的代码,运行800x800次:

下面的每个while循环在iter1 == lim之前运行正好800次,因此持续时间是在800x800x800(512百万)次运行时测量的。

iter1iter2limdouble指针。它们指向double的足够大的矢量。

sumdouble本地变量。

s1s2是本地unsigned int' s,均等于800。

首先在2.257秒内运行:

while ( iter1 < lim )
{
    sum += *iter1 * *iter2;
    ++iter1;
    iter2 += s2;
}

第二次在7.364秒内运行:

while ( iter1 < lim )
{
    sum += *iter1 * *iter2;
    iter1 += s1;
    iter2 += s2;
}

第三次在1.355秒内运行:

while ( iter1 < lim )
{
    sum += *iter1 * *iter2;
    ++iter1;
    ++iter2;
}

如果我从每个指令中删除sum += *iter1 * *iter2;指令,它们都会在1.07秒左右运行。

如果删除第二次乘法并将指令更改为sum += *iter1;,则第一次和第三次运行在1.33秒内运行,而第二次运行则在1.46秒内运行。

如果我删除其他迭代器,如:sum += *iter2;,则第一次和第二次运行在2.2秒左右,而第三次运行在1.35秒内。

显然,效果下降与添加到iter1iter2的数量挂钩。我不是处理器访问内存和取消引用指针的专家,所以我希望社区中的某个人比我更了解并愿意解决我的问题。

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

编辑:问题是,与其他功能相比,第二个功能很慢,并且想要知道我能做些什么来让它运行得更快,因为它似乎做了类似的事情,就像其他2

编辑2:所有测量均在发布版本中进行

3 个答案:

答案 0 :(得分:5)

性能差异与迭代器无关。不同之处在于额外的缓存未命中率超过单位步幅的大量数据。

答案 1 :(得分:5)

这只是数据位置的一种表现形式。 在第一页的下一页上查看某个内容的时间比在第800页的内容上花费的时间少。在家尝试自己。

答案 2 :(得分:1)

我的猜测是生成的机器代码,具体取决于编译器/平台的软件化。

要检索指针值,内部机器将使用类似LOAD指令的东西,让我们调用虚构的汇编程序代码LD addr0

addr0指的是使用的地址寄存器。

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

我使用了一些只能生成addr0+语句的编译器,如果地址增量是由增量运算符直接在dereferenciation语句之后或之后完成的。

所以最后一个可能是具有最高效机器代码的示例。

如果您可以为每个示例发布编译过程的结果汇编代码,那将会很有趣。