我有3个函数可以归结为下面的代码,运行800x800次:
下面的每个while
循环在iter1 == lim
之前运行正好800次,因此持续时间是在800x800x800(512百万)次运行时测量的。
iter1
,iter2
和lim
是double
指针。它们指向double
的足够大的矢量。
sum
是double
本地变量。
s1
和s2
是本地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秒内。
显然,效果下降与添加到iter1
和iter2
的数量挂钩。我不是处理器访问内存和取消引用指针的专家,所以我希望社区中的某个人比我更了解并愿意解决我的问题。
如果您需要有关硬件的任何信息,我可以运行这些测试,或者其他任何可以证明有用的信息,请随时在评论中提问。
编辑:问题是,与其他功能相比,第二个功能很慢,并且想要知道我能做些什么来让它运行得更快,因为它似乎做了类似的事情,就像其他2编辑2:所有测量均在发布版本中进行
答案 0 :(得分:5)
性能差异与迭代器无关。不同之处在于额外的缓存未命中率超过单位步幅的大量数据。
答案 1 :(得分:5)
这只是数据位置的一种表现形式。 在第一页的下一页上查看某个内容的时间比在第800页的内容上花费的时间少。在家尝试自己。
答案 2 :(得分:1)
我的猜测是生成的机器代码,具体取决于编译器/平台的软件化。
要检索指针值,内部机器将使用类似LOAD指令的东西,让我们调用虚构的汇编程序代码LD addr0
。
addr0
指的是使用的地址寄存器。
许多CPU提供LD addr0+
之类的语句,在加载存储的值后递增地址。通常,这个额外的增量不会导致任何额外的周期。
我使用了一些只能生成addr0+
语句的编译器,如果地址增量是由增量运算符直接在dereferenciation语句之后或之后完成的。
所以最后一个可能是具有最高效机器代码的示例。
如果您可以为每个示例发布编译过程的结果汇编代码,那将会很有趣。