AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign FreePascal Schnittmenge von mehreren Mengen ermitteln
Thema durchsuchen
Ansicht
Themen-Optionen

Schnittmenge von mehreren Mengen ermitteln

Offene Frage von "Horst_"
Ein Thema von Laser · begonnen am 11. Mär 2012 · letzter Beitrag vom 21. Mär 2012
 
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#23

AW: Schnittmenge von mehreren Mengen ermitteln

  Alt 19. Mär 2012, 19:42
Ich habe meine Asm-Version aus #35 noch einmal überarbeitet.
Die nachstehende Funktion arbeitet mit 32 und 64 Bit Daten und ist (auf meinem Rechner) deutlich schneller, als die aus #35.
Mit den von Laser in #53 genannten Testdaten liefert sie korrekte Ergebnisse.

Die Umstellung von 32 auf 64 Bit habe ich so gelöst :

Delphi-Quellcode:
{$DEFINE INT64DATA}
type
   TElement={$IFDEF INT64DATA} int64 {$ELSE} integer {$ENDIF} ;
   TSampleArray=Array of TElement;
   TFiles=Array of TSampleArray;
var
   files:TFiles;
Wenn files die Daten enthält, dann ist der Ablauf so :

Delphi-Quellcode:
var len:integer;
begin
   len:=Length(files[0]);
   for i:=1 to High(files) do
      len:=GetIntersect_5(files[0], files[i],len);
   SetLength(files[0],len);
end;
Danach ist files[0] der Intersect.

Delphi-Quellcode:
FUNCTION GetIntersect_5(var Intersect,Data:TSampleArray; Len:integer):integer;
const f={$IFDEF INT64DATA} 8 {$ELSE} 4 {$ENDIF};
asm
// IN : EAX=@Intersect, EDX=@Data, ECX=Anzahl der Elemente der bisherigen Schnittmenge
// Out : EAX=Neue Anzahl der Elemente der Schnittmenge
               // Alle Register retten
               pushad // Temp:=ESP; Push EAX,ECX,EDX,EBX,Temp,EBP,ESI,EDI
               // Prüfen ob Data leer
               mov esi,[edx] // @Data[0]
               test esi,esi
               je @ReturnZero // Data ist leer
               mov edi,[eax] // @Intersect[0]
               test edi,edi
               je @ReturnZero // Intersect leer
               // Zeiger in Intersect und Data hinter jeweils letzten Eintrag
               // stellen und Indizes auf jeweils ersten Eintrag ausrichten
               lea edi,[edi+ecx*f] // @Intersect[Len]
               neg ecx // i [edi+ecx*4] = Intersect[0]
               je @ReturnZero // 0 Elemente in Intersect
               mov ebp,ecx // k [edi+ebp*4] = Intersect[0]
               mov ebx,[esi-4] // Length(data)
               lea esi,[esi+ebx*f] // @Data[Length(data)]
               neg ebx // j [esi+edx*4] = Data[0]
               jmp @Entry

@Store: mov [edi+ebp*f],eax // In neuem Intersect speichern
               {$IFDEF INT64DATA}
               mov [edi+ebp*f+4],edx // Hi wenn int64
               {$ENDIF};
               add ebp,1 // Neue Anzahl in Intersect
               add ecx,1 // Nächster Intersect-Index
               je @SetRes // Fertig
               mov eax,[edi+ecx*f] // Zahl aus Intersect laden
               {$IFDEF INT64DATA}
               mov edx,[edi+ecx*f+4] // Hi wenn int64
               {$ENDIF};
@NextData: add ebx,1 // Nächster Data-Index
               je @SetRes // Fertig
@Compare: {$IFDEF INT64DATA}
               cmp edx,[esi+ebx*f+4] // Vergleich Intersect, Data (Hi)
               ja @NextData // Intersect>Data. Nur Data-Index erhöhen
               jb @NextI
               {$ENDIF};
               cmp eax,[esi+ebx*f] // Vergleich Intersect, Data
               je @Store // Gleich. Speichern und beide Indizes erhöhen
               ja @NextData // Intersect>Data. Nur Data-Index erhöhen
@NextI: add ecx,1 // Nächster Intersect-Index
               je @SetRes // Fertig
@Entry: mov eax,[edi+ecx*f] // Zahl aus Intersect laden
               {$IFDEF INT64DATA}
               mov edx,[edi+ecx*f+4] // Hi wenn int64
               {$ENDIF};
               jmp @Compare

@SetRes: add ebp,[esp+24] // Alte Länge addieren (ebp ist <= 0)
               jmp @StoreRes

@ReturnZero: xor ebp,ebp
@StoreRes: mov [esp+28],ebp // von da wird sie in EAX gepopt
               popad
end;
Dass die Performance weitestgehend durch das Einlesen der Daten von der Platte bestimmt wird ist auch mir klar.
Mir geht es hier nur um den Wettbewerb der von Furtbichler ins Leben gerufen wird, mit der Voraussetzung "Daten komplett im RAM".
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz