Announcement

Collapse
No announcement yet.

Anwenden von logischen (bitweise) Operatoren -Jetzt aber Byte-weise

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Anwenden von logischen (bitweise) Operatoren -Jetzt aber Byte-weise

    Die neue herausforderung:

    Vorhanden: Ein Array a aus 600000 Array's mit jeweils 32 byte-werten und
    ein hilfs-Array s mit einer integer-representation des ersten Arrays, wobei
    die bit-masken dieser integer auskunft darüber erteilen, ob im a-Array an
    der position eine 0 oder ein anderer wert vorhanden ist.

    var a: array[0..600000] of array[0..31] of byte;
    var s: array[0..600000] of integer;

    Die anforderung an den algorithmus ist prinzipiell die gleiche, wie
    in der letzten diskussion. Es geht darum, alle elemente des arrays a
    untereinander zu vergleichen, um fest zu stellen, inwiefern sie sich
    jeweils unterscheiden. Von interesse sind solche fundstellen, bei denen
    sich die array's in einer einzigen stelle im byte-array unterscheiden,
    wobei eines der beiden verglichenen array's dort eine 0 stehen haben
    muss.

    <pre>
    // hilfsvariablen
    n,d,i: integer;
    e: extended;

    for n:=0 to length(a)-1 do
    begin

    // alle elemente durchlaufen
    for x:=n+1 to length(a)-1 do
    begin

    // differenz-maske bilden
    d := s[x] XOR s[n];

    if (d>0) then
    begin

    // stellen ermitteln, wo unterschiede vorliegen
    // nur wenn sich eine einzelne stelle unterscheidet,
    // ist e ganzzahlig
    e:=log2(d);
    if( frac(e)=0 )then
    begin

    d:=trunc(e);
    // d enthält nun die position der einzigen abweichung

    // diejenigen ausschliessen, die in den gesetzten
    // bytes unterschiedliche werte haben
    for i:=0 length(a[n])-1 do
    if (d<>-1) // nur solange prüfen, wie wir einen potentiellen treffer haben
    and (i<>d) // diesen index brauchen wir nicht prüfen
    and (a[n][i]<>0) and (a[x][i]<>0) // beide arrays müssen an der zu prüfenden position einen wert
    // ungleich 0 haben
    and ( a[n][i]<>a[x][i] ) // die eigentliche prüfung
    then d:=-1; // falls sich die arrays hier unterscheiden,
    // haben wir keinen treffer

    // wenn d nun noch positiv ist, wissen wir, dass sich
    // die beiden array's an einer einzigen stelle (position d) unterscheiden
    // und zwar in der art, das eines der beiden dort den wert 0 hat
    if(d>=0)then
    begin
    {
    ... hier findet die verarbeitung statt
    }
    end;

    end;

    end;

    end;

    </pre>

    Das aufwendige bei diesen tests ist, zu prüfen, ob die byte-arrays
    bis auf die ermittelte position identisch sind - da ist meiner ansicht nach
    noch ein grosses optimierungspotential verborgen. Dieser algorithmus braucht mehrere stunden (inkl. der ergebnisverarbeitung) auf einem P4/2GHz...

  • #2
    Hallo Constantinus,

    ich schau mir das mal heute Abend an.

    Tschüß

    Torste

    Comment


    • #3
      Wenn du auch mit Floating Points und Logarithmus rumrechnest ist die Laufzeit kein Wunder.<br>
      Mach dir doch eine Tabelle von 256 Elementen in der drinsteht wieviele Bits das entsprechende Byte gesetzt hat. Damit kriegst du die Bitanzahl mit einem Zugriff "Bitanzahl[TestByte]"

      Comment


      • #4
        @Robert Marquardt

        Die operationen mit den Floats sind meiner ansicht nach unkritisch, da sie die cpu gut verarbeiten kann - versuche haben das auch gezeigt. Aber man kann das sicherlich performanter und etwas eleganter lösen, da stimme ich dir zu.

        > Was meinst du mit dieser tabelle? Und inwiefern kann mir die anzahl der gesetzten bits weiterhelfen

        Comment


        • #5
          Die Differenzmaske sagt dir welche Bits in den beiden Bytes unterschiedlich sind. Du willst ja nur etwas machen wenn genau ein Bit unterschiedlich ist, also AnzahlBits[Differenzmaske] = 1.<br>
          <pre>
          const
          AnzahlBits: array [0..255] of Integer =
          (
          0, 1, 1, 2, // alle Werte rechne ich jetzt nicht aus
          );
          </pre&gt

          Comment


          • #6
            hmm. warum hat dieses array bei dir 256 elemente? ich habe doch 600.000 byte-masken, die ich vergleichen will... das array müsste dann doch 600.000^2 elemente haben, damit ich für jede differenzmaske die anzahl bits speichern kann. Ausserdem müsste ich die anzahl der bits ja auch noch irgendwie ermitteln - die byte-masken sind nicht vorher bekannt. Verstehe ich dich irgendwie falsch

            Comment


            • #7
              Hallo Constantinus,

              mit dem Array AnzahlBits hat man eine elegante Möglichkeit die Anzahl der notwendigen Bitvergleiche stark zu reduzieren.

              z.B. wird die Zahl 8 durch ein gesetztes Bit dargestellt. Die 13 benötigt 3 Bit's. Daraus ergibt sich das ich nicht erst den Bitvergleich starten muß, weil ja mindestens 2 Bits unterschiedlich sind.

              Gruß

              Torste

              Comment


              • #8
                Das Array a ist fuer deinen Test voellig unerheblich, da ja das Hilfsarray s die Information 0 bzw nicht 0 fuer die 2 Bytes traegt.<br>
                Jedes gesetzte Bit der Hilfsmaske d besagt das sich das entsprechende Byte des einen Eintrags von dem des anderen Eintrags unterscheidet. Konsequenterweise muss eines der beiden Bytes 0 sein.<br>
                Jetzt willst du wissen ob genau ein Unterschied vorhanden ist. Du musst also die Bits in d zaehlen.<br>
                Hier habe ich mich geirrt, da ich die Bits in einem Byte zaehlen wollte. Dafuer taugt AnzahlBits aber auch. Einfach die Bytes von d extrahieren und die jeweilige Anzahl Bits zusammenzaehlen.<br><br>
                BTW Cardinal ist besser als Integer fuer die Variablen s, d usw

                Comment


                • #9
                  Hallo Robert,

                  vielleicht bin ich ja etwas begriffsstutzig, aber ich versteht nicht wie Du das Bitarray verwenden willst.

                  So wie ich Dich verstanden habe, ist in dem Array definiert wieviel Bits zur Darstellung der jeweiligen Zahl benötigt werden.

                  Du ermittels die Anzahl der Bits für beide Zahlen und errechnest die Differenz. Mit der erhaltenen Differenz liegt meiner Meinung nach noch kein endgültiges Ergebnis vor.

                  z.B. die Zahl 13 benötigt 3 Bit, die Zahl 131 benötigt ebenfalls 3 Bit, aber es sind im Binärvergleich 4 Bit's unterschiedlich.

                  Gruß

                  Torste

                  Comment


                  • #10
                    Ich habe den eindruck, ihr verlauft euch ein bissl, daher versuche ich nochmal die anforderungen an den test zu formulieren:

                    ich habe ein array a vorliegen, in dem 600.000 byte-arrays abgelegt sind. Die 600.000 arrays bestehen aus je 32 byte.

                    für jedes element e1 des array a müssen alle anderen elemente e2 gefunden werden, die folgende bedingung erfüllen:
                    - e1 und e2 unterscheiden sich an einer stelle in ihrem byte-array
                    - an dieser stelle muss entweder e1 oder e2 ein 0-byte stehen haben
                    - alle sonstigen stellen müssen identisch sein

                    das hilfsarray s habe ich eingeführt um geschickt prüfen zu können, ob sich die zwei kandidaten an mehr als zwei positionen unterscheiden (siehe log2-funktion).
                    es ist prinzipiell überflüssig - man kann diese prüfung auch am ausgangsarray a vollziehen

                    Comment


                    • #11
                      Die Arrays e1 und e2 bestehen aus 32 Bytes, bei denen jedes Byte entweder 0 oder 1 sein kann ? Warum werden diese Arrays nicht durch 32Bit Cardinals ersetzt, und dann reicht BitCount(e1 xor e2) = 1 aus. Damit wird durch einen einzigsten Zugriff auf 4 Bytes = Cardinal in einem Zuge 32 Zustände geprüft. Für BitCount(x) kann ich dir eine sehr effiziente Funktion geben.

                      Gruß Hage

                      Comment


                      • #12
                        @hagen:
                        nein, die arrays e1 und e2 enthalten byte-werte, jeweils irgendetwas zwischen 0 und 255.
                        wenn es nur boolsche werte wären hätte ich ja gar kein problem, mit dem ich euch hier belästigen müsste.
                        scheint so, dass das hilfarray s hier verwirrung stiftet: dieses enthält eine projektion des byte-arrays mit jeweils einer 1 an den stellen, an denen der wert im byte-array ungleich 0 ist

                        Comment


                        • #13
                          Warum du das Hilfsarray S überhaupt benötigst weis ich nicht so recht, da die normalen 32 Byte Arrays ausreichen. Um eine Schleife kommst du aber nicht rum.

                          <pre>
                          C := 0;
                          for I := 0 to 31 do
                          if (A[I] = 0) and (B[I] <> 0) then Inc(C) else
                          if (A[I] <> 0) and (B[I] = 0) then Inc(C);
                          </pre>

                          C sollte dann 1 sein in deinem Falle.
                          Du kannst nun diese Schleife durch cleveren Assembler beschleunigen. Es sollte möglich sein die 32 Byte arrays als 8 Cardinals anzusprechen und diese durch Unrolling ohne Loop zu vergleichen.

                          Allerdings, nach deiner Aussage willst du ALLE 32 Byte Arrays untereinander mit ALLEN anderen 32 byte arrays vergleichen !? Richtig ? das ist ein enormer Aufwand und sollte durch bessere Algorithmen erledigt werden.

                          Ich würde zB. als erstes alle 32 Byte Arrays in 32Bit Cardinals umwandeln. Dann wird dieses eindimensionale Cardinal array sortiert. Somit findest du alle Werte die identisch zueinander sind, und diese müssen dann nur einmalig mit ihrem Wert mit den anderen unterschiedlichen Werten verglichen werden. Als Vergleichoperator käme dann BitCount(A xor B) zur Anwendung. Die innere Schleife wäre damit wegoptimiert und durch hochoptimierte Algos. ersetzt.

                          Vielleicht wäre es besser wenn du uns den Algorithums als ganzes erklären würdest, und wozu er eigentlich dient. Meistens kann man an höherer "Denk"-Stelle ansetzen und deine Datenstrukturen daraufhin besser optimieren. Dadurch wäre es zB. möglich das du garnicht mehr solche Vergleiche machen musst.

                          Gruß Hage

                          Comment


                          • #14
                            z.b. würde man bei der Erzeugung deiner Array Struktur statt mit Arrays mit Tries (binären Bäumen arbeiten). Alle Arrays mit 0 im ersten Element würden dann sofort sortiert in diesen Trie eingefügt, usw. usw. Nun sind im Trie alle 32 Byte arrays mit erstem element 0 im selben Zweig des Tries. Auf Grund diesem Wissens weisst du sofort das alle Arrays mit einer führenden Null sich zu allen anderen Arrays mit nur einer Null sich um 2 Stellen unterscheiden. Sie müssen also überhaupt nicht mehr überprüft werden. usw. usw.

                            Eine andere Möglichkeit wäre ein Wechsel in der Darstellung der Arrays. Statt die reinen Daten zu speichern, würde man zu jedem Array nur eine Liste der Indexe an denen eine Null vorkommt speichern. Diese Liste würde dann sortiert. Die Vergleichoperation beschränkt sich nun darauf diese Indexarrays zu überprüfen. Dabei kann man enorm viele Operationen durch logischen Ausschluß effizient programmieren.
                            Zb. zwei solcher Index Listen können um 1 unterschiedlich sein wenn sie in der Anzahl der Nullen ebenfalls um 1 differieren.
                            Alle Indexlisten mit gleicher oder gerader unterschiedlicher Anzahl können nicht mehr um eine Null unterschiedlich sein.

                            Gruß Hage

                            Comment


                            • #15
                              <i>Allerdings, nach deiner Aussage willst du ALLE 32 Byte Arrays untereinander mit ALLEN anderen 32 byte arrays vergleichen !? Richtig ? das ist ein enormer Aufwand und sollte durch bessere Algorithmen erledigt werden.</i>
                              <br>
                              wir kommen der sache näher sehe ich. nach besseren algorithmen bin auch auf der suche.
                              <br>
                              es geht um folgendes: diese 600.000 array dienen der eindeutigen identifizierung. jede stelle in dem 32 byte-array ist ein schlüssel und dessen wert ist sozusagen eine id. wenn ein element identisch zu einem anderen element ist, mit der ausnahme, das eine eine id<>0 auf einem schlüssel hat, auf dem der andere eine id=0 trägt, so ist dieses element dem anderen direkt untergeordnet. welche elemente also einem bestimmten element direkt untergeordnet sind möchte ich herausfinden .
                              <br>
                              eine vorausgehende sortierung hat auch stattgefunden: von links nach rechts sind die elemente nach ihren ids aufsteigend sortiert.
                              <br>
                              der ansatz, die anzahl an vergleichen zu reduzieren gefällt mir. doch kann man nicht die information der bytes in 32bit wiedergeben, die bei den vergleichen notwendig ist.
                              <br>
                              die anforderung lautet ja u.a. das die elemente e1 und e2 abgesehen von einer stelle identisch sein müssen - also alle anderen bytes müssen den gleichen wert haben

                              Comment

                              Working...
                              X