循环展开的复杂性分析

时间:2014-12-16 05:28:14

标签: algorithm

我想知道如果你展开循环一次,完成程序所需的时间(禁止缓存效果和其他任何东西)是否有所不同。基本上,是否存在任何差异 2循环:for(i = 0; i < n; i++)for(i = 0; i < n/2; i++)如果你访问第二个循环中的元素数量是第一个循环的两倍?这两个循环是否需要相同的时间才能完成,或者在另一个循环之前完成?

3 个答案:

答案 0 :(得分:2)

复杂性分析不考虑展开:迭代N次的展开循环仍为O(n)。

展开的唯一好处就是减少开销。在典型的循环中,你必须重复做三件事:

  1. 检查您是否完成
  2. 执行循环的“payload”主体
  3. 调整循环计数器
  4. 如果循环重复N次,则这三个步骤中的每一个也重复N次。但请注意,第一步和最后一步是纯粹的开销:它们用于处理循环簿记。

    当您展开循环一次时,您会删除步骤1和3中的一半,而步骤2重复N次。复杂性是相同的,但开销仅为过去的50%。

    注意:由此得出的一个观察结果是,当您的有效负载活动的时间与开销的时间相当时,展开最有意义。例如,如果有效载荷需要10ms并且开销也是10ms,则消除50%的开销会使环路加速25%。如果开销为1毫秒且有效载荷为10毫秒,则展开只能返回0.5 / 11或4.5%。

答案 1 :(得分:0)

循环展开是一种优化形式,因为它减少了增量,比较和跳转操作的次数。 (虽然将实际的展开和其他优化留给编译器,但它通常会找到更有效的方法来实现它。如果你认为你知道的更好 - 证明它!)

但是,

展开不会改变问题的复杂性类别。问题的复杂性通常不是由诸如循环开销之类的常数因素决定的,并且实际上只能在更高的数字上运行。 (例如,O(n*log(n)) Quicksort或Mergesort通常仅用于分解列表以排序为短段,而O(n²) Insertsort则用于对那些由于较低开销进行排序。)

答案 2 :(得分:0)

如果每周期工作与循环开销相当,那么展开可能会提高性能。另一方面,您将在一个循环周期中执行更多指令。如果你的指令缓存很小并且已经填满,那么你的展开可能会让事情变得更糟。

尝试并衡量,这是证明或反驳猜测的唯一方法

为了有趣的阅读,这里是原始循环展开器,Duff的设备

http://www.lysator.liu.se/c/duffs-device.html#duffs-device

在一个紧凑的循环中它曾经给了我4%的提升