2011-09-06 109 views
0

以下哪个循环更快?我已经阅读了网络上的各种东西,包括Stack Overflow上的很多东西,我仍然不确定.net代码的真正答案是什么? .net中的字节码编译器是否有一些自动优化?我在这里找到了一个类似的帖子,但关于Java。 Efficiency of nested LoopVB.net嵌套For循环 - 效率

For n = 1 to 1000 
    For m = 1 to 2000 
     A(n,m) = b(n,m) 
Next m 
Next n 

或者,各地切换顺序:

For m = 1 to 2000 
    For n = 1 to 1000 
     A(n,m) = b(n,m) 
Next n 
Next m 

一个是因为它通过在内存中以便更快...。如果是这样?

+2

没关系。 – Kevin

+0

嗯,我想可能会有所作为,但我们必须看到'A(int,int)'的定义。实际上,你不应该担心它。 –

+0

为什么不尝试并找出答案? –

回答

1

我有我的TickTimer类,所以我决定试一试。 我不得不增加数组的大小以注意不同之处。
自己测试一下。第一个确实更快。

Module Module1 

    Sub Main() 
     Dim A(10000, 20000) As Int16 
     Dim b(10000, 20000) As Int16 

     For n = 1 To 10000 
      For m = 1 To 20000 
       A(n, m) = 1 
       b(n, m) = 1 
      Next m 
     Next n 

     Dim firstTick As TickTimer = New TickTimer() 
     For n = 1 To 10000 
      For m = 1 To 20000 
       A(n, m) = b(n, m) 
      Next m 
     Next n 
     Console.WriteLine(firstTick.DeltaSeconds("")) 

     Dim secondTick As TickTimer = New TickTimer() 
     For m = 1 To 20000 
      For n = 1 To 10000 
       A(n, m) = b(n, m) 
      Next n 
     Next m 
     Console.WriteLine(secondTick.DeltaSeconds("")) 

     Console.ReadKey() 

    End Sub 

End Module 


Public Class TickTimer 
    Public currentTicks As Long 
    Public lastTicks As Long = System.DateTime.Now.Ticks 
    Public retVal As String 
    ''' <summary> 
    ''' Calculates the seconds it took since the class was instantiated until this method 
    ''' is first invoked and for subsequent calls since the previous time the method was called 
    ''' </summary> 
    ''' <param name="message">Message (e.g. "The last query took ")</param> 
    ''' <returns>The passed string followed by the seconds: "   The last query took,  0.3456"</returns> 
    ''' <remarks>To see how long it takes a method to execute instantiate this class at its 
    ''' very begining and call this method just before it returns; Log the result with  Debug.Writeln or something similar</remarks> 
    Public Function DeltaSeconds(ByVal message As String) As String 
     currentTicks = System.DateTime.Now.Ticks 
     retVal = String.Format("{0}, {1}", message.PadLeft(100), ((currentTicks - lastTicks)/ TimeSpan.TicksPerSecond).ToString().PadRight(15)) 
     lastTicks = currentTicks 
     Return retVal 
    End Function 
End Class 
+0

谢谢这是非常有帮助的。 – GetFuzzy

0

Rick Sladkey完美地击中了这一点! 先前的测试都是先“按行”滚动同一个数组,然后“按列”滚动。下面是正确的测试,它对数组和其转置进行相同的操作。 在这种情况下,我们可以看到,实际上For Call的开销存在成本,第二种方法稍微快一些。如果我们按“列”滚动数组,这肯定是没有注意到的,这会产生更大数量级的计算时间。我不知道CLI阵列的细节,为什么这是处理器的行为,但这是证据。

Structure mt 
    Dim m() As Double 
End Structure 

Sub Main() 

    Dim a, b As Integer 
    Dim p As Integer = 10000000 
    Dim q As Integer = 5 
    Dim m1(p, q) As Double 
    Dim m4(q, p) As Double 
    'Dim m2()() As Double 
    'Dim m3() As mt 

    'ReDim m2(p) 
    'For a = 1 To p 
    ' ReDim m2(a)(q) 
    'Next 

    'ReDim m3(p) 
    'For a = 1 To p 
    ' ReDim m3(a).m(q) 
    'Next 

    Dim sw As New Stopwatch 

    sw.Restart() 
    For a = 1 To p 
     For b = 1 To q 
      m1(a, b) = 0 
      'm2(a)(b) = 0 
      'm3(a).m(b) = 0 
     Next 
    Next 
    sw.Stop() 

    Console.WriteLine("Small loop in large loop: " & sw.Elapsed.ToString()) 

    sw.Restart() 
    For a = 1 To q 
     For b = 1 To p 
      'm1(b, a) = 0 
      'm2(b)(a) = 0 
      'm3(b).m(a) = 0 
      m4(a, b) = 0 
     Next 
    Next 
    sw.Stop() 

    Console.WriteLine("Large loop in small loop: " & sw.Elapsed.ToString()) 
    Stop 
End Sub 
+0

对于两天前的大型(p = 10000000)的情况,我必须有一些其他进程在这个进程中强制进行分页。输出是:大循环中的小循环:00:02:27.1539801;小循环中的大循环:01:12:11.9496944。所以即使较小的缓存不会导致问题(他们这样做),如果您有足够的内存请求,其中一些内存在每个外部循环期间都被调出,那么您肯定会注意到性能上的巨大差异。 –