Alexander писал(а):
Её вначале удалось немного ускорить вручную, а затем этот замысел развил ИИ и вот что получилось.
Для органайзера я использую сейчас её 64 битную версию, но на всякий случай сделал и проверил 16 битную. Она работает ещё немного быстрее и совместима по параметру с функцией FPC SysUtils.IsLeapYear.
Так что вполне кандидат на замещение имеющихся в FPC этих функций. Ускорение в два с гаком раз.
Отдельно функция выглядит так:
Код: Выделить всё
function vg16(y : word) : bytebool; inline;
begin
Exit((y and 3 = 0) and ((y mod 25) <> 0) or (y and 15 = 0));
end;
Емнип, оптимизатор FPC-3.2.2 умеет заменять целочисленное деление на константу умножением только для оператора DIV, но не умеет для MOD:
Код: Выделить всё
program test;
{$mode objfpc}{$H+}
uses
SysUtils, StopWatch;
function IsLeapYear1(y: Word): Boolean;
begin
Result := (y and 3 = 0) and (y mod 25 <> 0) or (y and 15 = 0);
end;
{$push}{$B+}
function IsLeapYear2(y: Word): Boolean;
begin
{$if Fpc_FullVersion < 30301}
Result := (y and 3 = 0) and (y - (y div 25)*25 <> 0) or (y and 15 = 0);
{$else}
Result := (y and 3 = 0) and (y mod 25 <> 0) or (y and 15 = 0);
{$endif}
end;
{$pop}
const
DataSize = 10000000;
var
a: array of Word;
i: Integer;
sw: TStopWatch;
begin
WriteLn('FPC-',{$I %FpcVersion%},' ', {$I %FPCTargetCPU%});
Randomize;
SetLength(a, DataSize);
for i := 0 to High(a) do
a[i] := Word(Random(10000));
sw := TStopWatch.StartNew;
for i := 0 to High(a) do
IsLeapYear(a[i]); //built-in
sw.Stop;
WriteLn('IsLeapYear: ', sw.ElapsedMilliseconds.ToString+' ms.');
sw := TStopWatch.StartNew;
for i := 0 to High(a) do
IsLeapYear1(a[i]);
sw.Stop;
WriteLn('IsLeapYear1: ', sw.ElapsedMilliseconds.ToString+' ms.');
sw := TStopWatch.StartNew;
for i := 0 to High(a) do
IsLeapYear2(a[i]);
sw.Stop;
WriteLn('IsLeapYear2: ', sw.ElapsedMilliseconds.ToString+' ms.');
end.
>>>
Код: Выделить всё
FPC-3.2.2 x86_64
IsLeapYear: 153,5927 ms.
IsLeapYear1: 60,2301 ms.
IsLeapYear2: 25,8963 ms.
А транковый 3.3.1 научился
Код: Выделить всё
FPC-3.3.1 x86_64
IsLeapYear: 38,0221 ms.
IsLeapYear1: 38,3202 ms.
IsLeapYear2: 17,6842 ms.
А для x86 всё несколько менее драматично
Код: Выделить всё
FPC-3.2.2 i386
IsLeapYear: 55,5314 ms.
IsLeapYear1: 53,1172 ms.
IsLeapYear2: 27,5213 ms.
Код: Выделить всё
FPC-3.3.1 i386
IsLeapYear: 40,2913 ms.
IsLeapYear1: 41,8065 ms.
IsLeapYear2: 18,6108 ms.