我想知道如果你展开循环一次,完成程序所需的时间(禁止缓存效果和其他任何东西)是否有所不同。基本上,是否存在任何差异
2循环:for(i = 0; i < n; i++)
和for(i = 0; i < n/2; i++)
如果你访问第二个循环中的元素数量是第一个循环的两倍?这两个循环是否需要相同的时间才能完成,或者在另一个循环之前完成?
答案 0 :(得分:2)
复杂性分析不考虑展开:迭代N次的展开循环仍为O(n)。
展开的唯一好处就是减少开销。在典型的循环中,你必须重复做三件事:
如果循环重复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%的提升