Advertising
Paste Description for timings for http://stackoverflow
Compiler optimizations and CPU optimizations are interfering in such funny an unexpected ways...
- timings for http://stackoverflow
- Saturday, January 19th, 2013 at 5:02:02pm MST
- program Project1;
- {$APPTYPE CONSOLE}
- {$R *.res}
- uses
- Windows, SysUtils, DateUtils;
- type TStopWatch = class
- private
- fFrequency : TLargeInteger;
- fIsRunning: boolean;
- fIsHighResolution: boolean;
- fStartCount, fStopCount : TLargeInteger;
- procedure SetTickStamp(var lInt : TLargeInteger) ;
- function GetElapsedTicks: TLargeInteger;
- function GetElapsedMilliseconds: TLargeInteger;
- function GetElapsed: string;
- public
- constructor Create(const startOnCreate : boolean = false) ;
- procedure Start;
- procedure Stop;
- property IsHighResolution : boolean read fIsHighResolution;
- property ElapsedTicks : TLargeInteger read GetElapsedTicks;
- property ElapsedMilliseconds : TLargeInteger read GetElapsedMilliseconds;
- property Elapsed : string read GetElapsed;
- property IsRunning : boolean read fIsRunning;
- end;
- constructor TStopWatch.Create(const startOnCreate : boolean = false) ;
- begin
- inherited Create;
- fIsRunning := false;
- fIsHighResolution := QueryPerformanceFrequency(fFrequency) ;
- if NOT fIsHighResolution then fFrequency := MSecsPerSec;
- if startOnCreate then Start;
- end;
- function TStopWatch.GetElapsedTicks: TLargeInteger;
- begin
- result := fStopCount - fStartCount;
- end;
- procedure TStopWatch.SetTickStamp(var lInt : TLargeInteger) ;
- begin
- if fIsHighResolution then
- QueryPerformanceCounter(lInt)
- else
- lInt := MilliSecondOf(Now) ;
- end;
- function TStopWatch.GetElapsed: string;
- var
- dt : TDateTime;
- begin
- dt := ElapsedMilliseconds / MSecsPerSec / SecsPerDay;
- result := Format('%d days, %s', [trunc(dt), FormatDateTime('hh:nn:ss.z', Frac(dt))]) ;
- end;
- function TStopWatch.GetElapsedMilliseconds: TLargeInteger;
- begin
- result := (MSecsPerSec * (fStopCount - fStartCount)) div fFrequency;
- end;
- procedure TStopWatch.Start;
- begin
- SetTickStamp(fStartCount) ;
- fIsRunning := true;
- end;
- procedure TStopWatch.Stop;
- begin
- SetTickStamp(fStopCount) ;
- fIsRunning := false;
- end;
- function MirrorByte7Op(b : Byte) : Byte;
- begin
- Result :=
- ((b * $0802 and $22110) or (b * $8020 and $88440)) * $10101 shr 16;
- end;
- function MirrorByte7OpI(b : Byte) : Byte; inline;
- begin
- Result :=
- ((b * $0802 and $22110) or (b * $8020 and $88440)) * $10101 shr 16;
- end;
- function MirrorByte(b : Byte) : Byte;
- begin
- Result :=
- ((b and $01) shl 7) or
- ((b and $02) shl 5) or
- ((b and $04) shl 3) or
- ((b and $08) shl 1) or
- ((b and $10) shr 1) or
- ((b and $20) shr 3) or
- ((b and $40) shr 5) or
- ((b and $80) shr 7);
- end;
- function MirrorByteI(b : Byte) : Byte; inline;
- begin
- Result :=
- ((b and $01) shl 7) or
- ((b and $02) shl 5) or
- ((b and $04) shl 3) or
- ((b and $08) shl 1) or
- ((b and $10) shr 1) or
- ((b and $20) shr 3) or
- ((b and $40) shr 5) or
- ((b and $80) shr 7);
- end;
- function ReverseBits(b: Byte): Byte;
- var
- i: Integer;
- begin
- Result := 0;
- for i := 1 to 8 do
- begin
- Result := (Result shl 1) or (b and 1);
- b := b shr 1;
- end;
- end;
- function ReverseBits2(b: Byte): Byte;
- var
- i: Integer;
- begin
- Result := 0;
- for i := 1 to 8 do
- begin
- Result := (Result shr 1) or (b and $80);
- b := b shl 1;
- end;
- end;
- function BitFlipP(b: byte): byte;
- var i: integer;
- begin
- Result := 0;
- for i := 1 to 8 do
- begin
- Result := Result shl 1;
- if Odd(b) then Result := Result or 1;
- b := b shr 1;
- end;
- end;
- function BitFlipP2(b: byte): byte;
- var i: integer;
- begin
- Result := 0;
- for i := 1 to 8 do
- begin
- Result := Result shr 1;
- if (b and $80)<>0 then Result := Result or $80;
- b := b shl 1;
- end;
- end;
- function BitFlipA1(b: byte): byte; {X86 not X64}
- asm
- MOV EDX, EAX
- MOV ECX, 8
- @@1:
- SHR DL, 1
- RCL AL, 1
- LOOP @@1
- RET
- end;
- function BitFlipA2(b: byte): byte; {X86 not X64}
- asm
- MOV ECX, 8
- @@1:
- SHL AL, 1
- RCR DL, 1
- LOOP @@1
- MOVZX EAX, DL
- RET
- end;
- function BitFlipA3(b: byte): byte; {X86 not X64}
- asm
- MOV ECX, 8
- @@1:
- ADD AL, AL
- RCR DL, 1
- LOOP @@1
- MOVZX EAX, DL
- RET
- end;
- function BitFlipA4(b: byte): byte; {X86 not X64}
- asm
- MOV ECX, 8
- @@1:
- MOV AH, $80
- SHR DL, 1
- AND AH, AL
- OR DL, AH
- ADD AL, AL
- LOOP @@1
- MOV EAX, EDX
- RET
- end;
- function BitFlipA5(b: byte): byte; {X86 not X64}
- asm
- MOV ECX, 8
- @@1:
- MOV AH, 1
- ADD DL, DL
- AND AH, AL
- OR DL, AH
- SHR AL, 1
- LOOP @@1
- MOVZX EAX, DL
- RET
- end;
- function BitFlipA6(b: byte): byte; {X86 not X64}
- asm
- MOV ECX, 8
- PUSH EBX
- @@1:
- MOV BL, 1
- ADD DL, DL
- AND BL, AL
- OR DL, BL
- SHR EAX, 1
- LOOP @@1
- MOVZX EAX, DL
- POP EBX
- RET
- end;
- function BitFlipU(b: byte): byte; {X86 not X64}
- asm
- MOV EDX, EAX
- SHR EDX, 1
- RCL EAX, 1
- SHR EDX, 1
- RCL EAX, 1
- SHR EDX, 1
- RCL EAX, 1
- SHR EDX, 1
- RCL EAX, 1
- SHR EDX, 1
- RCL EAX, 1
- SHR EDX, 1
- RCL EAX, 1
- SHR EDX, 1
- RCL EAX, 1
- SHR EDX, 1
- RCL EAX, 1
- end;
- var LUT: array[Byte] of byte;
- function BitFlipLUT(b: byte): byte;
- begin
- Result := LUT[b];
- end;
- function BitFlipLUTi(b: byte): byte; inline;
- begin
- Result := LUT[b];
- end;
- var d, b: byte; i: integer;
- var
- sw : TStopWatch;
- const RunCount = 1000000000;
- begin
- try
- { TODO -oUser -cConsole Main : Insert code here }
- for b := 0 to 255 do
- begin
- d := MirrorByte(b);
- LUT[b] := d;
- Assert(d = MirrorByteI(b));
- Assert(d = MirrorByte7Op(b));
- Assert(d = MirrorByte7OpI(b));
- Assert(d = ReverseBits(b));
- Assert(d = ReverseBits2(b));
- Assert(d = BitFlipP(b));
- Assert(d = BitFlipP2(b));
- Assert(d = BitFlipA1(b));
- Assert(d = BitFlipA2(b));
- Assert(d = BitFlipA3(b));
- Assert(d = BitFlipA4(b));
- Assert(d = BitFlipA5(b));
- Assert(d = BitFlipA6(b));
- Assert(d = BitFlipU(b));
- end;
- WriteLN('Functions tested, LUT filled, starting timings...');
- sw := TStopWatch.Create() ;
- try
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := ReverseBits(i);
- end;
- sw.Stop;
- Writeln('Pascal AND original: ':30, sw.ElapsedMilliseconds:12);
- for i := 1 to RunCount do
- begin
- d := ReverseBits2(i);
- end;
- sw.Stop;
- Writeln('Pascal AND reversed: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipP(i);
- end;
- sw.Stop;
- Writeln('Pascal IF original: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipP(i);
- end;
- sw.Stop;
- Writeln('Pascal IF reversed: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipA1(i);
- end;
- sw.Stop;
- Writeln('Asm SHIFT 1: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipA2(i);
- end;
- sw.Stop;
- Writeln('Asm SHIFT 2: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipA3(i);
- end;
- sw.Stop;
- Writeln('Asm SHIFT 3: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipA4(i);
- end;
- sw.Stop;
- Writeln('Asm AND 1: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipA5(i);
- end;
- sw.Stop;
- Writeln('Asm AND 2: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipA6(i);
- end;
- sw.Stop;
- Writeln('Asm AND 3: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipU(i);
- end;
- sw.Stop;
- Writeln('Asm Shift unrolled: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipLUT(i)
- end;
- sw.Stop;
- Writeln('LUT, called: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := BitFlipLUTi(i);
- end;
- sw.Stop;
- Writeln('LUT, inlined: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := MirrorByte(i);
- end;
- sw.Stop;
- Writeln('Pascal unrolled: ':30, sw.ElapsedMilliseconds:12);
- sw.Start;
- for i := 1 to RunCount do
- begin
- d := MirrorByteI(i);
- end;
- sw.Stop;
- Writeln('Pas. unrolled, inlined: ':30, sw.ElapsedMilliseconds:12);
- for i := 1 to RunCount do
- begin
- d := MirrorByte7Op(i);
- end;
- sw.Stop;
- Writeln('Pascal math, called: ':30, sw.ElapsedMilliseconds:12);
- for i := 1 to RunCount do
- begin
- d := MirrorByte7OpI(i);
- end;
- sw.Stop;
- Writeln('Pascal math, inlined: ':30, sw.ElapsedMilliseconds:12);
- finally
- sw.Free;
- end;
- except
- on E: Exception do
- Writeln(E.ClassName, ': ', E.Message);
- end;
- ReadLN;
- end.
advertising
Update the Post
Either update this post and resubmit it with changes, or make a new post.
You may also comment on this post.
Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.