使用两个循环体还是一个循环体(结果相同)? [英] Use two loop bodies or one (result identical)?

查看:21
本文介绍了使用两个循环体还是一个循环体(结果相同)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在想,在更好地利用CPU缓存(众所周知,它受益于引用的局部性)方面,哪种方法更有效--两个循环,每个循环迭代同一数学数字集,每个循环都有不同的Body语句(例如,对集合中的每个元素调用一个函数),或者让一个Body循环执行两个(或更多)Body语句。在所有循环之后,我们假定应用程序状态相同。

在我看来,拥有两个循环将引入较少的缓存未命中和驱逐,因为循环使用的更多指令和数据可以放入缓存中。我说的对吗?

假设:

  1. fg调用的开销与循环开销相比微不足道

  2. fg各自单独使用大部分缓存,因此当一个接一个调用时缓存会溢出(单循环版本的情况)

  3. 英特尔酷睿双核CPU

  4. C语言源代码

  5. GCC编译器,不需要额外的开关

如果可能,我希望得到的答案不属于过早优化的性质。

我所倡导的双循环版本的一个例子:

int j = 0, k = 0;

for(int i = 0; i < 1000000; i++)
{
    j += f(i);
}

for(int i = 0; i < 1000000; i++)
{
    k += g(i);
}

推荐答案

我可以看到三个变量(即使在看似简单的代码块中也是如此):

  • f()g()做什么?它们中的一个可以使所有指令高速缓存线无效(有效地将另一个推出去)吗?这种情况是否也会发生在二级指令缓存中(不太可能)?那么,只保留其中一个可能是有益的。注意:倒数并不意味着"只有一个循环",因为:
  • 根据if()g()是否操作大量数据?然后,如果知道它们是否对同一数据集进行操作,那将是一件好事-同样,您必须考虑对两个不同的数据集进行操作是否会因缓存未命中而搞砸。
  • 如果和确实如您第一次声明那样是原始的,我假设在代码大小以及运行时间和代码复杂性方面都是如此,那么缓存位置问题不会出现在像这样的小代码块中--您最担心的是如果其他进程被调度有实际工作要做,并使所有缓存失效,直到轮到您的进程运行。
最后一个想法:考虑到这样的进程在您的系统中可能很少发生(我用"Rare"这个词也相当随意),您可以考虑将两个函数内联,并让编译器展开循环。这是因为对于指令高速缓存来说,故障返回到L2并不是什么大问题,并且包含i, j, k的单个高速缓存线在该循环中被无效的可能性看起来并不那么可怕。然而,如果不是这样,一些更多的细节将是有用的。

这篇关于使用两个循环体还是一个循环体(结果相同)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆