Schneller vergleich zweier arrays

  • VB.NET

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von mcdt.

    Schneller vergleich zweier arrays

    Hey Community,
    Ich habe derzeit ein performance problem. Ich möchte 2 arrays vergleichen um einen operator für ein inventar zu erstellen.
    Da dieser Vergleich oft Aufgerufen wird kann ich KEINE schleifen verwenden. Derzeit sieht mein code wie folgt aus:

    VB.NET-Quellcode

    1. Public Shared Operator =(ByVal i1 As Inventory, ByVal i2 As Inventory)
    2. Try
    3. For i As Integer = 0 To i1.Items.Count - 1
    4. If i1.Items(i) <> i2.Items(i) Then
    5. Return False
    6. End If
    7. Next
    8. Return True
    9. Catch
    10. Return False
    11. End Try
    12. End Operator

    Die public variable Items vom Inventory ist ein 1 Dimensionaller array vom typ integer.
    Ich habe einen tipp bekommen der wie folgt aus sieht:

    VB.NET-Quellcode

    1. Return i1.Items + i2.Items = i1.Items * 2

    leider gibt es die operatoren array + array und array * integer nicht :/
    Ich hoffe jemand weiß wie man einen derartigen vergleich schneller lösen kann.

    Danke im voraus 8-)
    Hi
    Schlechter Tipp. Erstens kann es zu arithmetischen Überläufen führen und zweitens ist der Integer-Vergleich bereits auf der Hardware implementiert. Arrays sind außerdem nicht als mathematische Vektoren anzusehen und haben afaik keinen +-Operator. Wenn du zwei Arrays vergleichen möchtest bleibt dir aber wohl fast nichts anderes über, außer alle Array-Elemente zu vergleichen. Das kannst du entweder in Form einer Rekursion oder einer Iteration, wie du es gerade machst, gestalten. Wie groß sind denn die Arrays und woher kommen sie?

    Übrigens kannst du das Try-Catch weglassen, indem du einfach die Array.Length-Eigenschaft vergleichst.

    Gruß
    ~blaze~
    20 Integer? Das geht eigentlich flott. Multithreading wäre natürlich auch eine Möglichkeit. Zum Beispiel: Erzeuge Threads, die beim Start eine Methode aufrufen, die eine Schleife enthält und über ein AutoResetEvent pausiert werden. Sobald ein neuer Job verfügbar ist laufen die Threads so lange, bis der vergleichende Index die Länge erreicht. Der Index ist halt der Index der zu vergleichenden Arrays. Du musst allerdings immer ein SyncLock über die Klasse erstellen, da sonst der Index nicht inkrementiert werden kann (kommt zu einer Überschneidung von Auslesen und schreiben). Das Problem ist halt, dass das SyncLock die Performance reduziert und wahrscheinlich die Methode mit einem Thread schneller ist...

    Try-Catches nach Möglichkeit bitte vermeiden.

    Gruß
    ~blaze~
    Das Problem ist nur, das diese Methode im laufe des Spieles einige 100 male in der Sekunde aufgerufen wird, und es dadurch zu extremen laggs oder freezes kommt. Das Programm kommt nicht hinterher. Ich bezweifel auch das, jeden index ohne schleife aufzurufen viel schneller ist. Ausserdem ist es viel umständlicher. Da sich der Array auch fast so oft ändert, wie er überprüft wird, ist es sinnlos zu überprüfen ob sich über die methoden "add" und "subtract", die ich geschrieben hab, was geändert hat. Im Grunde genommen ist das auf diese Art kaum möglich...

    Mhh :/
    Was für ein Spiel ? Was sind das für Werte (innerhalb) des Spiels, dass diese verglichen werden müssen ? Vielleicht gibt es da eine bessere Lösung.
    Die 20 Aufrufe machen da echt nichts aus. Das wär echt ein Wunder... Das liegt eher an was anderem. Schleifen sind einfach Sprungbefehle im IL-Code. Das Array lädt einfach den Wert mit dem Index i auf den 1. Wert auf den Stack, dann den 2. Wert und führt einen Vergleichsbefehl aus. Anschließend wird der Index i inkrementiert und zurück gesprungen, wenn i < der Array-Länge. Da lässt sich wirklich fast nichts an Performance gewinnen. Hau die ganzen Try-Catch-Abschnitte einfach mal raus und beschreibe genauer, was dein Spiel macht.

    Gruß
    ~blaze~
    Nach einiger zeit hängt sich das Spiel auf, wenn es zu viele Updates/sek gibt. Dabei hängt er dann Minuten an solchen Schleifen, bis er dann normal fortfährt. Wiederrum muss ich dazu sagen das das Spiel darauf programmiert wurde alles was während einer freeze time nicht ausgeführt wurde nachzuholen. Demnach kommt es zu dauerhaften freezes. Bei bestimmt 10.000+ zeilen ist es recht schwer nachzuverfolgen woher der lagg letztenendes kommt. Da er, wie bereits gesagt, sehr lange an den Schleifen hängt, vermute ich das der fehler dort liegt.
    Bei einem Integer-Vergleich von 20 Elementen ist das Aufsetzen eines zweiten Threads ein größerer Overhead als der Vergleich selbst.

    Ich würde es (zumindest testweise) von der anderen Seite angehen:
    Werden die Elemente in regelmässigen Abständen abgeglichen?
    Sobald du ein Element im Array veränderst (also einen anderen Wert reischreibst, als schon drin steht), invalidierst du das ganze Array.

    Alternativ:
    Erstelle ein Bit-Array mit 32 Bit (20 macht keinen Sinn) und setze jedesmal, wenn du das Array beschreibst das korrespondierende Bit auf 1 bei Ungleichheit zwischen den Array-Elementen und auf 0 bei Gleichheit.
    Am Schluss musst du dann nur noch die Bitmaske auf 0 überprüfen.

    Es hängt halt davon ab, wie häufig du schreibst und wie häufig du vergleichen musst.
    Wenn das Array sich (laut deiner Aussage) eher weniger ändert verändert, als es verglichen wird, dürfte das die schnellere Variante sein.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Bis jetzt nutze ich noch kein Multithreading. Ich denke das dies aber Sinn macht, und vorallem das ofte Vergleichen, Umrechnen, Umsetzen und neu Zeichnen der Performance den Rest gibt. Eventuell sollte ich weitere Intervalle an einigen stellen einfügen. Das Problem ist, das zu große Intervalle dem Gameplay schaden, zu niedrige der Performance. Ich hab das Gefühl mein Kopf platzt gleich, kann aber auch daran liegen das ich Krank bin.

    Edit: Mit deiner Methode braucht man doch glatt eine Schleife mehr, immerhin muss der Array ja auch beschrieben werden.

    Mangafreak1995 schrieb:

    Was für ein Spiel ? Was sind das für Werte (innerhalb) des Spiels, dass diese verglichen werden müssen ? Vielleicht gibt es da eine bessere Lösung.