Excel 令人惊讶的嵌套循环持续时间
我的VBA代码中有一个内部循环和外部循环。我认为总的执行时间可以估计为外循环计数*内循环计数,但情况似乎并非如此,因为执行10*10^8操作大约需要5秒,但执行10^8*10操作大约需要24秒。与多次重复内部循环相比,多次重复外部循环似乎使总执行时间更长,尽管两个示例中的操作总数保持不变。它应该这样工作吗?为什么呢?我做错什么了吗Excel 令人惊讶的嵌套循环持续时间,excel,vba,Excel,Vba,我的VBA代码中有一个内部循环和外部循环。我认为总的执行时间可以估计为外循环计数*内循环计数,但情况似乎并非如此,因为执行10*10^8操作大约需要5秒,但执行10^8*10操作大约需要24秒。与多次重复内部循环相比,多次重复外部循环似乎使总执行时间更长,尽管两个示例中的操作总数保持不变。它应该这样工作吗?为什么呢?我做错什么了吗 Sub test() Dim i As Long Dim j As Long Dim t As Single maxI = 0 '1 maxJ = 9 '1 bil
Sub test()
Dim i As Long
Dim j As Long
Dim t As Single
maxI = 0 '1
maxJ = 9 '1 bilion
Do While maxJ >= 0
t = Timer
For i = 1 To 10 ^ maxI
For j = 1 To 10 ^ maxJ
Next j
Next i
Debug.Print maxI + maxJ & " " & maxI & " " & maxJ & " " & Timer - t
maxI = maxI + 1
maxJ = maxJ - 1
Loop
End Sub
结果数据集以外部循环中的双线性重复和内部循环中的一个重复开始,如下所示:
+-------------------+-----------------+-----------------+----------+
| total_operations | outer_loop_cnt | inner_loop_cnt | time |
+-------------------+-----------------+-----------------+----------+
| 9 | 9 | 0 | 222,2305 |
| 9 | 8 | 1 | 24,52734 |
| 9 | 7 | 2 | 8,300781 |
| 9 | 6 | 3 | 5,683594 |
| 9 | 5 | 4 | 5,070313 |
| 9 | 4 | 5 | 5,109375 |
| 9 | 3 | 6 | 5,167969 |
| 9 | 2 | 7 | 4,933594 |
| 9 | 1 | 8 | 4,898438 |
| 9 | 0 | 9 | 5,109375 |
+-------------------+-----------------+-----------------+----------+
+---+---+---+----------+
| 9 | 0 | 9 | 4,800781 |
| 9 | 1 | 8 | 4,890625 |
| 9 | 2 | 7 | 4,808594 |
| 9 | 3 | 6 | 4,800781 |
| 9 | 4 | 5 | 4,757813 |
| 9 | 5 | 4 | 4,972656 |
| 9 | 6 | 3 | 5,308594 |
| 9 | 7 | 2 | 6,980469 |
| 9 | 8 | 1 | 24,54297 |
| 9 | 9 | 0 | 222,3828 |
+---+---+---+----------+
Do While maxJ >= 0
upper_i = 10 ^ maxI
upper_j = 10 ^ maxJ
t = Timer
For i = 1 To upper_i
For j = 1 To upper_j
...
结果数据集以内部循环中的bilion重复和外部循环中的一个重复开始,如下所示:
+-------------------+-----------------+-----------------+----------+
| total_operations | outer_loop_cnt | inner_loop_cnt | time |
+-------------------+-----------------+-----------------+----------+
| 9 | 9 | 0 | 222,2305 |
| 9 | 8 | 1 | 24,52734 |
| 9 | 7 | 2 | 8,300781 |
| 9 | 6 | 3 | 5,683594 |
| 9 | 5 | 4 | 5,070313 |
| 9 | 4 | 5 | 5,109375 |
| 9 | 3 | 6 | 5,167969 |
| 9 | 2 | 7 | 4,933594 |
| 9 | 1 | 8 | 4,898438 |
| 9 | 0 | 9 | 5,109375 |
+-------------------+-----------------+-----------------+----------+
+---+---+---+----------+
| 9 | 0 | 9 | 4,800781 |
| 9 | 1 | 8 | 4,890625 |
| 9 | 2 | 7 | 4,808594 |
| 9 | 3 | 6 | 4,800781 |
| 9 | 4 | 5 | 4,757813 |
| 9 | 5 | 4 | 4,972656 |
| 9 | 6 | 3 | 5,308594 |
| 9 | 7 | 2 | 6,980469 |
| 9 | 8 | 1 | 24,54297 |
| 9 | 9 | 0 | 222,3828 |
+---+---+---+----------+
Do While maxJ >= 0
upper_i = 10 ^ maxI
upper_j = 10 ^ maxJ
t = Timer
For i = 1 To upper_i
For j = 1 To upper_j
...
更新:如果我修改代码,使上界不会像下面这样计算每个循环:
+-------------------+-----------------+-----------------+----------+
| total_operations | outer_loop_cnt | inner_loop_cnt | time |
+-------------------+-----------------+-----------------+----------+
| 9 | 9 | 0 | 222,2305 |
| 9 | 8 | 1 | 24,52734 |
| 9 | 7 | 2 | 8,300781 |
| 9 | 6 | 3 | 5,683594 |
| 9 | 5 | 4 | 5,070313 |
| 9 | 4 | 5 | 5,109375 |
| 9 | 3 | 6 | 5,167969 |
| 9 | 2 | 7 | 4,933594 |
| 9 | 1 | 8 | 4,898438 |
| 9 | 0 | 9 | 5,109375 |
+-------------------+-----------------+-----------------+----------+
+---+---+---+----------+
| 9 | 0 | 9 | 4,800781 |
| 9 | 1 | 8 | 4,890625 |
| 9 | 2 | 7 | 4,808594 |
| 9 | 3 | 6 | 4,800781 |
| 9 | 4 | 5 | 4,757813 |
| 9 | 5 | 4 | 4,972656 |
| 9 | 6 | 3 | 5,308594 |
| 9 | 7 | 2 | 6,980469 |
| 9 | 8 | 1 | 24,54297 |
| 9 | 9 | 0 | 222,3828 |
+---+---+---+----------+
Do While maxJ >= 0
upper_i = 10 ^ maxI
upper_j = 10 ^ maxJ
t = Timer
For i = 1 To upper_i
For j = 1 To upper_j
...
对于更大的外部循环,我得到了更好的结果。但似乎这仍然是事实,最好是内外循环运行次数几乎相等,以获得最佳性能。对我来说,这仍然令人惊讶。有什么想法吗
9 9 0 60,07031
9 8 1 14,8125
9 7 2 10,36719
9 6 3 9,414063
9 5 4 9,507813
9 4 5 9,40625
9 3 6 9,523438
9 2 7 9,835938
9 1 8 12,875
9 0 9 11,02344
9 0 9 9,75
9 1 8 9,257813
9 2 7 9,265625
9 3 6 9,273438
9 4 5 9,1875
9 5 4 9,164063
9 6 3 9,21875
9 7 2 10,42969
9 8 1 14,96094
9 9 0 59,66406
顺便说一句,如何设置表格格式?是的,这很有意义
For
循环边界始终在循环开始时计算。因此,如果你运行内循环十亿次,你要计算10^maxI
一次,然后10^maxJ
一次,然后是j=j+1的十亿次重复。
如果运行外循环十亿次,你要计算10^maxI
一次,和10^maxJ
和j=j+1
10亿次。这也是我的解释。在如此高的重复次数下,计算会变得昂贵。检查是否存在这种情况的一个好方法是预先计算10^Max并将其设置为for循环值。哪些数据类型是maxI
,maxJ
,upper\u i
,以及upper\u j
?它们都是Long吗?我已经显式地将所有这些属性输入为Long,但这并没有显著的区别。