AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

pack-Funktion optimieren

Ein Thema von luke2 · begonnen am 4. Feb 2012 · letzter Beitrag vom 5. Feb 2012
Antwort Antwort
jbg

Registriert seit: 12. Jun 2002
3.485 Beiträge
 
Delphi 10.1 Berlin Professional
 
#1

AW: pack-Funktion optimieren

  Alt 4. Feb 2012, 19:28
Viel lässt sich da nicht optimieren.
Oh, doch. Die 64bit Div- und Mod-Operationen sind sehr teuer und zudem auch nicht für Divisoren kleiner 2^32 optimiert. Und wenn man dann noch das Div und Mod in einem Schwung ermittelt, kann man da noch einiges rausholen.
Aber auch entfernen der String-Konkatenation tut sein übriges dazu.

Delphi-Quellcode:
function UDivMod6432(const Dividend: Int64; Divisor: LongWord; var Rest: LongWord): Int64;
// DivMod64 für "Divisor < 2^32"
{$IFDEF CPUX64}
asm
  // in: RCX = Dividend
  // EDX = Divisor
  // R8 = @Rest
  // out: RAX = Quotient
  mov rax, rcx // Register für die Division (RDX:RAX / RCX) vorbereiten
  mov ecx, edx // Divisor in ECX für die Division schieben
  xor rdx, rdx

  //div ecx // "Divisor < 2^32" ausnutzen
  db $F7, $F1 // XE2 compiler bug, es wird immer "div rcx" generiert

  mov dword ptr [r8], edx // Rest in "Rest" schreiben
end;
{$ELSE}
asm
  // in: [ebp+$0c]:[ebp+$08] = Dividend
  // EAX = Divisor
  // EDX = @Rest
  // out: EDX:EAX = Quotient
  push ebx
  push edx // Zeiger auf Rest sichern
  mov ecx, eax

  mov eax, dword ptr [ebp+$0c] // HIGH DWORD des Dividenden als LOW DWORD für die Division laden
  xor edx, edx // kein HIGH DWORD bei der Division
  div ecx // und dividieren (EDX enthält Rest, der als Übertrag genutzt wird)

  mov ebx, eax // HIGH DWORD des Quotienten sichern
  mov eax, dword ptr [ebp+$08] // LOW DWORD des Dividenden laden
  div ecx // und dividieren (EDX enthält Rest)

  pop ecx // Zeiger auf Rest wiederherstellen
  mov dword ptr [ecx], edx // Rest in "Rest" schreiben
  mov edx, ebx // HIGH DWORD des Quotienten wiederherstellen
  pop ebx
end;
{$ENDIF CPUX64}

function cvbase_ANSI(n: Int64): AnsiString;
var
  Buf: array[0..7] of AnsiChar;
  Index: Integer;
  r: LongWord;
begin
  Index := Length(Buf);
  while n > 0 do
  begin
    Dec(Index);
    n := UDivMod6432(n, 255, r);
    Buf[Index] := chtab[r];
  end;
  SetString(Result, PAnsiChar(@Buf[Index]), Length(Buf) - Index);
end;

function cvbase(n: Int64): string;
var
  Buf: array[0..7] of Char;
  Index: Integer;
  r: LongWord;
begin
  Index := Length(Buf);
  while n > 0 do
  begin
    Dec(Index);
    n := UDivMod6432(n, 255, r);
    Buf[Index] := chtab[r];
  end;
  SetString(Result, PChar(@Buf[Index]), Length(Buf) - Index);
end;
UPDATE: Die 32bit assembler Version nahm eine falsche Parameterreihenfolge an.

Geändert von jbg ( 5. Feb 2012 um 17:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#2

AW: pack-Funktion optimieren

  Alt 4. Feb 2012, 20:17
Ne Frage, warum wird #10 ignoriert? (Sag nicht, wegen dem Zeilenumbruch)
Falls du nämlich mit der Basis 256 (und nicht 255) arbeiten könntest, wäre das um einiges einfacher:

Delphi-Quellcode:
function cvbase(n:int64): string;
begin
  SetLength(Result, 8);
  Move(n, Result[1], 8);
end;
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.399 Beiträge
 
Delphi 12 Athens
 
#3

AW: pack-Funktion optimieren

  Alt 4. Feb 2012, 20:25
string AnsiString
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
luke2

Registriert seit: 17. Jun 2009
117 Beiträge
 
#4

AW: pack-Funktion optimieren

  Alt 5. Feb 2012, 17:20
Danke jbg, das sieht schon sehr gut aus, allerdings erhalte ich in der Zeile
div ecx // und dividieren (EDX enthält Rest, der als Übertrag genutzt wird) immer den Fehler Division durch Null, egal mit welchen Werten ich cvbase aufrufe.

Ne Frage, warum wird #10 ignoriert? (Sag nicht, wegen dem Zeilenumbruch)
Die Strings werden später in eine Datei gespeichert und deshalb wird ein (beliebiges) Zeichen benötigt um einen string von dem anderen zu unterscheiden.
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.485 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5

AW: pack-Funktion optimieren

  Alt 5. Feb 2012, 17:26
Der Fehler sollte jetzt ausgebessert sein. Ich hatte noch ein wenig mit der Reihenfolge der Parameter gespielt und dabei die 32bit Assemblerversion nicht richtig angepasst.
  Mit Zitat antworten Zitat
luke2

Registriert seit: 17. Jun 2009
117 Beiträge
 
#6

AW: pack-Funktion optimieren

  Alt 5. Feb 2012, 17:31
Dann sage ich mal vielen Dank, es ist ungefähr 4x schneller als meine Version!
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#7

AW: pack-Funktion optimieren

  Alt 5. Feb 2012, 17:56
Ne Frage, warum wird #10 ignoriert? (Sag nicht, wegen dem Zeilenumbruch)
Die Strings werden später in eine Datei gespeichert und deshalb wird ein (beliebiges) Zeichen benötigt um einen string von dem anderen zu unterscheiden.
Machs doch anders:
Code:
<Länge des Blcoks><Block> <Länge des Blcoks><Block> <Länge des Blcoks><Block>
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Antwort Antwort


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 14:07 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