一个循环有两个动作VS两个循环有一个动作性能?

时间:2015-02-23 21:34:09

标签: c# performance loops

我很长时间对这个新手问题感兴趣。

例如,我们有两种情况:

  1. 我有一个带有两个函数的循环。 (WhileFor并不重要。)

    for (int i = 0; i < 1000; i++)
    {
        Function_1();
        Function_2();
    }
    
  2. 我有两个循环,每个循环一次。

    for (int i = 0; i < 1000; i++)
    {
        Function_1();
    }
    
    for (int i = 0; i < 1000; i++)
    {
        Function_2();
    }
    
  3. 我知道首先会更快。

    但这两种情况之间的性能速度有何不同? (百分比)

    如果最大循环次数增加,性能会下降多少?

    在这种情况下,什么(处理器或RAM)承担更大的负载?

1 个答案:

答案 0 :(得分:3)

从纯粹的理论角度来看,两者之间没有区别。无论哪种方式,它是O(N),那就是结束。

从更实际的角度来看,缓存可以改变这个简单的答案。可以比另一个更有效地使用缓存。那个赢了一定是你展示的第一个。

在真实的(现代)计算机上,它基本上可以解决这个问题,从而更有效地利用缓存。

反过来,这取决于每个Function_1Function_2使用了多少内存。如果Function_1和Function_2各自涉及执行相当多的代码,那么它们中的每一个都将适合L1指令缓存,但是它们两者一起赢得了,然后第二个版本可能会更快。在这种情况下,第一个版本(在两个函数之间交替)必须在每次执行时从主存储器加载每个函数,因此从主存储器加载代码〜2000次。使用第二个,从内存中加载Function_1的代码一次,从缓存中执行1000次,然后对Function_2执行相同的操作。主存储器共有2个负载。

在另一个方向,让我们假设Function_1和Function_2的代码都可以适合指令缓存,但是Function_1和Function_2都在相同的数据上运行,并且该数据的总数太大而无法容纳在数据缓存中。

这通常会逆转这种情况:对数据块执行Function_1,然后对同一数据块执行Function_2只会从内存中加载一次数据,然后对其进行所有必要的计算,然后加载下一个块数据,等等。每个数据块只从主存储器加载一次。

在这种情况下,代码的第二个版本可能会慢大约2倍 - 它会加载一块内存并在其上执行Function_1。然后它将加载第二块内存,并在其上执行Function_1,依此类推。一旦使用Function_1处理了所有内存,它将返回并加载所有相同的内存块以对其执行Function_2。

整个研究领域包括缓存感知和缓存遗忘算法,以帮助为像您这样的案例做出明智的选择。缓存感知排序基于上述(更详细的版本)模型,选择如何组织计算以适应缓存组织。缓存无关的算法更多地针对相对通用的缓存模型,并提供良好的性能,几乎与具体缓存的确切组织方式无关。