VB.net Nested For Loop - Эффективность - PullRequest
0 голосов
/ 06 сентября 2011

Какой из следующих циклов быстрее?Я читал все виды вещей в сети, в том числе много вещей здесь, в Переполнении стека, и я до сих пор не уверен, что ответ на самом деле для кода .net?Есть ли некоторая автоматическая оптимизация компилятором байт-кода в .net?Я нашел похожий пост, но о Java здесь. Эффективность вложенного цикла

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 ]

1 голос
/ 06 сентября 2011

У меня был класс 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 голосов
/ 29 августа 2012

Рик Слэдки отлично вписался!Предыдущие тесты прокручивают один и тот же массив сначала «по строкам», а затем «по столбцам».Ниже приведен правильный тест, который выполняет те же операции над массивом и его транспонированием.В этом случае мы можем видеть, что на самом деле есть издержки на вызов For, и второй метод немного быстрее.Это определенно незаметно, если мы прокручиваем массив «по столбцам», что дает время вычисления большего порядка.Я не знаю подробностей о массивах 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
...