Delphi-PRAXiS
Seite 6 von 6   « Erste     456   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Function für Vorzeichen? (https://www.delphipraxis.net/76719-function-fuer-vorzeichen.html)

uligerhardt 10. Sep 2006 00:40

Re: Function für Vorzeichen?
 
Zitat:

Zitat von 3_of_8
Das geht schneller:

Delphi-Quellcode:
function signmultiply(const a, b: Extended): Extended;
begin
  result:=a;
  PByte(Integer(@result)+9)^:=PByte(Integer(@result)+9)^ xor
    (PByte(Integer(@b)+9)^ and (1 shl 7));
end;
c:=signmultiply(a, b) macht in etwa das: if b<0 then c:=-a else c:=a;

Ihr habt doch alle nen Schlag. :-) Wer will denn so nen Code haben, um vielleicht drei Nanosekunden zu sparen?

3_of_8 10. Sep 2006 00:41

Re: Function für Vorzeichen?
 
Es kommt darauf an, wie oft das aufgerufen wird. Du solltest mal die abs()-Funktion der Math-Unit sehen. Die ist vielleicht optimiert, sag ich dir.

JasonDX 10. Sep 2006 00:50

Re: Function für Vorzeichen?
 
Zitat:

Zitat von 3_of_8
Es kommt darauf an, wie oft das aufgerufen wird.

Wenn bei einer Prozedur der Aufruf fast gleich lang braucht wie die Ausfuerhung des Inhalt selbst, dann sind solche Optimierungen eher zweitrangig. Und wenn eine Funktion um 1% schneller ist als eine andere, dann spielt es keine Rolle, wie oft sie aufgerufen wird - ich spare mir immer nur 1% der Zeit. Und nachdem wir nicht mehr um 1970 leben, als CPU-Zeit mit Barem bezahlt wurde, wuerde ich bei so geringen Laufzeitunterschieden eher auf Lesbarkeit setzen.

greetz
Mike

3_of_8 10. Sep 2006 00:53

Re: Function für Vorzeichen?
 
Das sehe ich anders. Bei so grundlegenden, also so eigentlich primitiven Funktionen jedenfalls. Bei einer sehr speziellen Funktion, die selten aufgerufen wird, kann das wieder anders aussehen. Aber wenn mein Code oft wiederverwendet wird, optimiere ich ihn lieber.

Und so ein if kann den Prozessor nunmal ordentlich ausbremsen, daher vermeide ich es nunmal gerne.

r2c2 10. Sep 2006 11:31

Re: Function für Vorzeichen?
 
Hallo :hi:
hab die Diskussion hier von anfang an verfolgt. Warum? Weils IMHO sehr interessant is, wie man doch so ne einfache Funktion auf unterschiedlichste Art schreiben kann. Aus der ganzen Optimiererei lernt man doch so einiges...

Zitat:

Zitat von 3_of_8
Das sehe ich anders. Bei so grundlegenden, also so eigentlich primitiven Funktionen jedenfalls. Bei einer sehr speziellen Funktion, die selten aufgerufen wird, kann das wieder anders aussehen. Aber wenn mein Code oft wiederverwendet wird, optimiere ich ihn lieber.

IMHO bringt Optimierung nur was, wenn die Funktion in einer langen Schleife aufgerufen wird. Ansonsten is das mehr lernen, wie man mit Algorithmen umgeht...

Zitat:

Und so ein if kann den Prozessor nunmal ordentlich ausbremsen, daher vermeide ich es nunmal gerne.
Echtzeitprogrammierung wär was für dich. :wink: Da gehts nämlcih wirklich um jede Mikrosekunde. Ergo: Möglichst keine Sprünge, schon gar keine bedingten. Divisionen vermeiden. Viel rumschieben, ... N DSP is eben etwas langsamer als ne PC CPU. Und, wenn das ganze auch noch alle paarhundert *Mikro*sekunden passieren soll, ...

In diesem Fall is aber IMHO ne lesbare Version besser. Der Quotent Code-Kommentar / Geschwindigkeit is nämlich annähernd konstant... Und ich hab, wenns auf n paar Mikrosekunden hin oder her nicht ankommt lesbaren code lieber, als schnellen...

mfg

Christian

Amateurprofi 10. Sep 2006 13:09

Re: Function für Vorzeichen?
 
Zitat:

Zitat von 3_of_8
Das sehe ich anders. Bei so grundlegenden, also so eigentlich primitiven Funktionen jedenfalls. Bei einer sehr speziellen Funktion, die selten aufgerufen wird, kann das wieder anders aussehen. Aber wenn mein Code oft wiederverwendet wird, optimiere ich ihn lieber.

Und so ein if kann den Prozessor nunmal ordentlich ausbremsen, daher vermeide ich es nunmal gerne.

@3_of_8 :

Wenn Du schon bei "eigentlich pimitiven" Funktionen lieber optimierst, warum machst Du das denn nicht konsequent ?

Ich hab mal Deinen Vorschlag und zwei Alternativen getestet.
Für jeweils 1000000 Durchläufe habe ich gemessen (P4, 2.66 GHz)
Dein Vorschlag = 38.7 ms
Alternative 1 = 16.1 ms
Alternative 2 = 5.6 ms, also knapp 7 mal so schnell wie Deine Version....


Ich denke, daß ca. sieben mal so schnell eine Assemblerversion rechtfertigt.

Und warum ist Deine Funktion so bummelig ?
Schau Dir das ganze doch mal im Debugger in der CPU-Ansicht an.

Du übergibst 2 Extended Werte als Const Parameter (weil du meints das bringe Vorteile ?). Bringt aber nichts. Es werden nicht etwa Pointer in Registern übergeben sondern die Parameter werden auf dem Stack übergeben.

Tatsächlich passiert in etwa folgendes.
1) a und b werden auf den Stack gelegt. Dann wird Deine Funktion aufgerufen.
2) das "result:=a" legt a dann noch einmal auf den Stack.
3) dann kommt die Berechnung des Vorzeichens, was auch nicht ganz so schnell abläuft.
4) abschließend wird result vom Stack in die FPU geladen. (Extended Werte werden im TOS zurück gegeben.)
5) und wird dann nach Rückkehr aus Deiner Funktion in c gestellt.

Und warum sind die Alternativen so schnell ? Schaue es Dir mal im Debugger an....

Bei allen Versionen ist übrigens, wenn a=0 und b negativ ist, das Resultat -0 (ja, die FPU unterscheidet zwischen positiver 0 und negativer 0). Ob das bei irgenwelchen Berechnungen Auswirkungen hat, ist mir nicht bekannt.

Alternative 1
Delphi-Quellcode:
PROCEDURE xSignMultiply(var a,b,c:extended);
asm
      fld  TByte [eax]
      test Byte [edx+9],$80
      je   @1
      fchs
@1:  fstp TByte [ecx]
end;
Das "if" und der ev. damit verbundene Sprung kostet übrigens so gut wie gar nichts.

Alternative 2
Delphi-Quellcode:
PROCEDURE ySignMultiply(var a,b,c:extended);
asm
      push ebx
      mov  ebx,[eax]
      mov  [ecx],ebx
      mov  ebx,[eax+4]
      mov  [ecx+4],ebx
      mov  ax,[eax+8]
      mov  bx,[edx+8]
      and  bx,$8000
      xor  ax,bx
      mov  [ecx+8],ax
      pop  ebx
end;
Der Vollständigkeit wegen Dein Vorschlag
Delphi-Quellcode:
function signmultiply(const a, b: Extended): Extended;
begin
  result:=a;
  PByte(Integer(@result)+9)^:=PByte(Integer(@result)+9)^ xor
    (PByte(Integer(@b)+9)^ and (1 shl 7));
end;
Und mit folgender Prozedur hab ich die Zeiten gemessen.
Delphi-Quellcode:
PROCEDURE TMain.Test;
var a,b,c:extended; i:integer; q0,q1,q2,q3:int64; s1,s2,s3:string;
begin
   a:=-200;
   b:=-300;

   queryperformancecounter(q0);
   for i:=1 to 1000000 do c:=SignMultiply(a,b);
   queryperformancecounter(q1);
   dec(q1,q0);

   queryperformancecounter(q0);
   for i:=1 to 1000000 do xSignMultiply(a,b,c);
   queryperformancecounter(q2);
   dec(q2,q0);

   queryperformancecounter(q0);
   for i:=1 to 1000000 do ySignMultiply(a,b,c);
   queryperformancecounter(q3);
   dec(q3,q0);

   QueryPerformanceFrequency(q0);
   str((q1/q0):0:6,s1);
   str((q2/q0):0:6,s2);
   str((q3/q0):0:6,s3);
   ShowMessage(s1+#13+s2+#13+s3);
end;

3_of_8 10. Sep 2006 13:43

Re: Function für Vorzeichen?
 
Normalerweise hätte ich das mit Assembler gemacht, aber ich kenne mich dafür noch nicht gut genug mit der FPU aus.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:37 Uhr.
Seite 6 von 6   « Erste     456   

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 by Thomas Breitkreuz