Part of Slepp's ProjectsPastebinTURLImagebinFilebin
Feedback -- English French German Japanese
Create Upload Newest Tools Donate
Sign In | Create Account

Paste Description for timings for http://stackoverflow

Compiler optimizations and CPU optimizations are interfering in such funny an unexpected ways...

timings for http://stackoverflow
Sunday, January 20th, 2013 at 12:02:02am UTC 

  1. program Project1;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8.   Windows, SysUtils, DateUtils;
  9.  
  10. type TStopWatch = class
  11.    private
  12.      fFrequency : TLargeInteger;
  13.      fIsRunning: boolean;
  14.      fIsHighResolution: boolean;
  15.      fStartCount, fStopCount : TLargeInteger;
  16.      procedure SetTickStamp(var lInt : TLargeInteger) ;
  17.      function GetElapsedTicks: TLargeInteger;
  18.      function GetElapsedMilliseconds: TLargeInteger;
  19.      function GetElapsed: string;
  20.    public
  21.      constructor Create(const startOnCreate : boolean = false) ;
  22.      procedure Start;
  23.      procedure Stop;
  24.      property IsHighResolution : boolean read fIsHighResolution;
  25.      property ElapsedTicks : TLargeInteger read GetElapsedTicks;
  26.      property ElapsedMilliseconds : TLargeInteger read GetElapsedMilliseconds;
  27.      property Elapsed : string read GetElapsed;
  28.      property IsRunning : boolean read fIsRunning;
  29.    end;
  30.  
  31.  constructor TStopWatch.Create(const startOnCreate : boolean = false) ;
  32.  begin
  33.    inherited Create;
  34.  
  35.    fIsRunning := false;
  36.  
  37.    fIsHighResolution := QueryPerformanceFrequency(fFrequency) ;
  38.    if NOT fIsHighResolution then fFrequency := MSecsPerSec;
  39.  
  40.    if startOnCreate then Start;
  41.  end;
  42.  
  43.  function TStopWatch.GetElapsedTicks: TLargeInteger;
  44.  begin
  45.    result := fStopCount - fStartCount;
  46.  end;
  47.  
  48.  procedure TStopWatch.SetTickStamp(var lInt : TLargeInteger) ;
  49.  begin
  50.    if fIsHighResolution then
  51.      QueryPerformanceCounter(lInt)
  52.    else
  53.      lInt := MilliSecondOf(Now) ;
  54.  end;
  55.  
  56.  function TStopWatch.GetElapsed: string;
  57.  var
  58.    dt : TDateTime;
  59.  begin
  60.    dt := ElapsedMilliseconds / MSecsPerSec / SecsPerDay;
  61.    result := Format('%d days, %s', [trunc(dt), FormatDateTime('hh:nn:ss.z', Frac(dt))]) ;
  62.  end;
  63.  
  64.  function TStopWatch.GetElapsedMilliseconds: TLargeInteger;
  65.  begin
  66.    result := (MSecsPerSec * (fStopCount - fStartCount)) div fFrequency;
  67.  end;
  68.  
  69.  procedure TStopWatch.Start;
  70.  begin
  71.    SetTickStamp(fStartCount) ;
  72.    fIsRunning := true;
  73.  end;
  74.  
  75.  procedure TStopWatch.Stop;
  76.  begin
  77.    SetTickStamp(fStopCount) ;
  78.    fIsRunning := false;
  79.  end;
  80.  
  81.  
  82.  
  83. function MirrorByte7Op(b : Byte) : Byte;
  84. begin
  85.   Result :=
  86.     ((b * $0802 and $22110) or (b * $8020 and $88440)) * $10101 shr 16;
  87. end;
  88.  
  89. function MirrorByte7OpI(b : Byte) : Byteinline;
  90. begin
  91.   Result :=
  92.     ((b * $0802 and $22110) or (b * $8020 and $88440)) * $10101 shr 16;
  93. end;
  94.  
  95. function MirrorByte(b : Byte) : Byte;
  96. begin
  97.   Result :=
  98.     ((b and $01) shl 7) or
  99.     ((b and $02) shl 5) or
  100.     ((b and $04) shl 3) or
  101.     ((b and $08) shl 1) or
  102.     ((b and $10) shr 1) or
  103.     ((b and $20) shr 3) or
  104.     ((b and $40) shr 5) or
  105.     ((b and $80) shr 7);
  106. end;
  107.  
  108. function MirrorByteI(b : Byte) : Byte; inline;
  109. begin
  110.   Result :=
  111.     ((b and $01) shl 7) or
  112.     ((b and $02) shl 5) or
  113.     ((b and $04) shl 3) or
  114.     ((b and $08) shl 1) or
  115.     ((b and $10) shr 1) or
  116.     ((b and $20) shr 3) or
  117.     ((b and $40) shr 5) or
  118.     ((b and $80) shr 7);
  119. end;
  120.  
  121. function ReverseBits(b: Byte): Byte;
  122. var
  123.   i: Integer;
  124. begin
  125.   Result := 0;
  126.   for i := 1 to 8 do
  127.   begin
  128.     Result := (Result shl 1) or (b and 1);
  129.     b := b shr 1;
  130.   end;
  131. end;
  132.  
  133. function ReverseBits2(b: Byte): Byte;
  134. var
  135.   i: Integer;
  136. begin
  137.   Result := 0;
  138.   for i := 1 to 8 do
  139.   begin
  140.     Result := (Result shr 1) or (b and $80);
  141.     b := b shl 1;
  142.   end;
  143. end;
  144.  
  145. function BitFlipP(b: byte): byte;
  146. var i: integer;
  147. begin
  148.   Result := 0;
  149.  
  150.   for i := 1 to 8 do
  151.   begin
  152.     Result := Result shl 1;
  153.     if Odd(b) then Result := Result or 1;
  154.     b := b shr 1;
  155.   end;
  156. end;
  157.  
  158. function BitFlipP2(b: byte): byte;
  159. var i: integer;
  160. begin
  161.   Result := 0;
  162.  
  163.   for i := 1 to 8 do
  164.   begin
  165.     Result := Result shr 1;
  166.     if (b and $80)<>0 then Result := Result or $80;
  167.     b := b shl 1;
  168.   end;
  169. end;
  170.  
  171. function BitFlipA1(b: byte): byte; {X86 not X64}
  172. asm
  173.   MOV EDX, EAX
  174.   MOV ECX, 8
  175.   @@1:
  176.     SHR DL, 1
  177.     RCL AL, 1
  178.     LOOP @@1
  179.  
  180.   RET
  181. end;
  182.  
  183. function BitFlipA2(b: byte): byte; {X86 not X64}
  184. asm
  185.   MOV ECX, 8
  186.   @@1:
  187.     SHL AL, 1
  188.     RCR DL, 1
  189.     LOOP @@1
  190.  
  191.   MOVZX EAX, DL
  192.   RET
  193. end;
  194.  
  195. function BitFlipA3(b: byte): byte; {X86 not X64}
  196. asm
  197.   MOV ECX, 8
  198.   @@1:
  199.     ADD AL, AL
  200.     RCR DL, 1
  201.     LOOP @@1
  202.  
  203.   MOVZX EAX, DL
  204.   RET
  205. end;
  206.  
  207. function BitFlipA4(b: byte): byte; {X86 not X64}
  208. asm
  209.   MOV ECX, 8
  210.   @@1:
  211.     MOV AH, $80
  212.     SHR DL, 1
  213.     AND AH, AL
  214.      OR DL, AH
  215.     ADD AL, AL
  216.     LOOP @@1
  217.  
  218.   MOV EAX, EDX
  219.   RET
  220. end;
  221.  
  222. function BitFlipA5(b: byte): byte; {X86 not X64}
  223. asm
  224.   MOV ECX, 8
  225.   @@1:
  226.     MOV AH, 1
  227.     ADD DL, DL
  228.     AND AH, AL
  229.      OR DL, AH
  230.     SHR AL, 1
  231.     LOOP @@1
  232.  
  233.   MOVZX EAX, DL
  234.   RET
  235. end;
  236.  
  237. function BitFlipA6(b: byte): byte; {X86 not X64}
  238. asm
  239.   MOV ECX, 8
  240.   PUSH EBX
  241.   @@1:
  242.     MOV BL, 1
  243.     ADD DL, DL
  244.     AND BL, AL
  245.      OR DL, BL
  246.     SHR EAX, 1
  247.     LOOP @@1
  248.  
  249.   MOVZX EAX, DL
  250.   POP EBX
  251.   RET
  252. end;
  253.  
  254. function BitFlipU(b: byte): byte; {X86 not X64}
  255. asm
  256.     MOV EDX, EAX
  257.  
  258.     SHR EDX, 1
  259.     RCL EAX, 1
  260.  
  261.     SHR EDX, 1
  262.     RCL EAX, 1
  263.  
  264.     SHR EDX, 1
  265.     RCL EAX, 1
  266.  
  267.     SHR EDX, 1
  268.     RCL EAX, 1
  269.  
  270.     SHR EDX, 1
  271.     RCL EAX, 1
  272.  
  273.     SHR EDX, 1
  274.     RCL EAX, 1
  275.  
  276.     SHR EDX, 1
  277.     RCL EAX, 1
  278.  
  279.     SHR EDX, 1
  280.     RCL EAX, 1
  281. end;
  282.  
  283. var LUT: array[Byte] of byte;
  284.  
  285. function BitFlipLUT(b: byte): byte;
  286. begin
  287.    Result := LUT[b];
  288. end;
  289.  
  290. function BitFlipLUTi(b: byte): byte; inline;
  291. begin
  292.    Result := LUT[b];
  293. end;
  294.  
  295. var d, b: byte; i: integer;
  296.  
  297. var
  298.    sw : TStopWatch;
  299.  
  300. const RunCount = 1000000000;
  301.  
  302. begin
  303.   try
  304.     { TODO -oUser -cConsole Main : Insert code here }
  305.     for b := 0 to 255 do
  306.       begin
  307.         d := MirrorByte(b);
  308.         LUT[b] := d;
  309.  
  310.         Assert(d = MirrorByteI(b));
  311.         Assert(d = MirrorByte7Op(b));
  312.         Assert(d = MirrorByte7OpI(b));
  313.         Assert(d = ReverseBits(b));
  314.         Assert(d = ReverseBits2(b));
  315.         Assert(d = BitFlipP(b));
  316.         Assert(d = BitFlipP2(b));
  317.         Assert(d = BitFlipA1(b));
  318.         Assert(d = BitFlipA2(b));
  319.         Assert(d = BitFlipA3(b));
  320.         Assert(d = BitFlipA4(b));
  321.         Assert(d = BitFlipA5(b));
  322.         Assert(d = BitFlipA6(b));
  323.         Assert(d = BitFlipU(b));
  324.       end;
  325.  
  326.    WriteLN('Functions tested, LUT filled, starting timings...');
  327.  
  328.    sw := TStopWatch.Create() ;
  329.    try
  330.      sw.Start;
  331.  
  332.      for i := 1 to RunCount do
  333.         begin
  334.           d := ReverseBits(i);
  335.         end;
  336.      sw.Stop;
  337.      Writeln('Pascal AND original: ':30, sw.ElapsedMilliseconds:12);
  338.  
  339.      for i := 1 to RunCount do
  340.         begin
  341.           d := ReverseBits2(i);
  342.         end;
  343.      sw.Stop;
  344.      Writeln('Pascal AND reversed: ':30, sw.ElapsedMilliseconds:12);
  345.  
  346.      sw.Start;
  347.      for i := 1 to RunCount do
  348.         begin
  349.           d := BitFlipP(i);
  350.         end;
  351.      sw.Stop;
  352.      Writeln('Pascal IF original: ':30, sw.ElapsedMilliseconds:12);
  353.  
  354.      sw.Start;
  355.      for i := 1 to RunCount do
  356.         begin
  357.           d := BitFlipP(i);
  358.         end;
  359.      sw.Stop;
  360.      Writeln('Pascal IF reversed: ':30, sw.ElapsedMilliseconds:12);
  361.  
  362.      sw.Start;
  363.      for i := 1 to RunCount do
  364.         begin
  365.           d := BitFlipA1(i);
  366.         end;
  367.      sw.Stop;
  368.  
  369.      Writeln('Asm SHIFT 1: ':30, sw.ElapsedMilliseconds:12);
  370.  
  371.      sw.Start;
  372.      for i := 1 to RunCount do
  373.         begin
  374.           d := BitFlipA2(i);
  375.         end;
  376.      sw.Stop;
  377.      Writeln('Asm SHIFT 2: ':30, sw.ElapsedMilliseconds:12);
  378.  
  379.      sw.Start;
  380.      for i := 1 to RunCount do
  381.         begin
  382.           d := BitFlipA3(i);
  383.         end;
  384.      sw.Stop;
  385.      Writeln('Asm SHIFT 3: ':30, sw.ElapsedMilliseconds:12);
  386.  
  387.      sw.Start;
  388.      for i := 1 to RunCount do
  389.         begin
  390.           d := BitFlipA4(i);
  391.         end;
  392.      sw.Stop;
  393.      Writeln('Asm AND 1: ':30, sw.ElapsedMilliseconds:12);
  394.  
  395.      sw.Start;
  396.      for i := 1 to RunCount do
  397.         begin
  398.           d := BitFlipA5(i);
  399.         end;
  400.      sw.Stop;
  401.      Writeln('Asm AND 2: ':30, sw.ElapsedMilliseconds:12);
  402.  
  403.      sw.Start;
  404.      for i := 1 to RunCount do
  405.         begin
  406.           d := BitFlipA6(i);
  407.         end;
  408.      sw.Stop;
  409.      Writeln('Asm AND 3: ':30, sw.ElapsedMilliseconds:12);
  410.  
  411.      sw.Start;
  412.      for i := 1 to RunCount do
  413.         begin
  414.           d := BitFlipU(i);
  415.         end;
  416.      sw.Stop;
  417.      Writeln('Asm Shift unrolled: ':30, sw.ElapsedMilliseconds:12);
  418.  
  419.      sw.Start;
  420.      for i := 1 to RunCount do
  421.         begin
  422.           d := BitFlipLUT(i)
  423.         end;
  424.      sw.Stop;
  425.      Writeln('LUT, called: ':30, sw.ElapsedMilliseconds:12);
  426.  
  427.      sw.Start;
  428.      for i := 1 to RunCount do
  429.         begin
  430.           d := BitFlipLUTi(i);
  431.         end;
  432.      sw.Stop;
  433.      Writeln('LUT, inlined: ':30, sw.ElapsedMilliseconds:12);
  434.  
  435.      sw.Start;
  436.  
  437.      for i := 1 to RunCount do
  438.         begin
  439.           d := MirrorByte(i);
  440.         end;
  441.      sw.Stop;
  442.      Writeln('Pascal unrolled: ':30, sw.ElapsedMilliseconds:12);
  443.  
  444.      sw.Start;
  445.  
  446.      for i := 1 to RunCount do
  447.         begin
  448.           d := MirrorByteI(i);
  449.         end;
  450.      sw.Stop;
  451.      Writeln('Pas. unrolled, inlined: ':30, sw.ElapsedMilliseconds:12);
  452.  
  453.      for i := 1 to RunCount do
  454.         begin
  455.           d := MirrorByte7Op(i);
  456.         end;
  457.      sw.Stop;
  458.      Writeln('Pascal math, called: ':30, sw.ElapsedMilliseconds:12);
  459.  
  460.      for i := 1 to RunCount do
  461.         begin
  462.           d := MirrorByte7OpI(i);
  463.         end;
  464.      sw.Stop;
  465.      Writeln('Pascal math, inlined: ':30, sw.ElapsedMilliseconds:12);
  466.  
  467.    finally
  468.      sw.Free;
  469.    end;
  470.  
  471.  
  472.   except
  473.     on E: Exception do
  474.       Writeln(E.ClassName, ': ', E.Message);
  475.   end;
  476.   ReadLN;
  477. end.

Update the Post

Either update this post and resubmit it with changes, or make a new post.

You may also comment on this post.

update paste below
details of the post (optional)

Note: Only the paste content is required, though the following information can be useful to others.

Save name / title?

(space separated, optional)



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.

comments powered by Disqus
worth-right
worth-right