2011-09-06 46 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。所以即使較小的緩存不會導致問題(他們這樣做),如果您有足夠的內存請求,其中一些內存在每個外部循環期間都被調出,那麼您肯定會注意到性能上的巨大差異。 –