Страница 1 из 1
Ускоренная версия функции определения високосного года
Добавлено: 15.12.2025 20:49:51
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;
В составе последней версии органайзера (юнит time.pas):
http://soft.self-made-free.ru/GORG64_503.tar.xz
там также есть последние ускорения и для других функций времени, но эта функция ускорена наиболее сильно.
Re: Ускоренная версия функции определения високосного года
Добавлено: 16.12.2025 07:45:45
Снег Север
Просто интересно - где может пригодиться ускорение в два раза определения високосного года??? Существуют приложения, где это требуется делать в реальном времени тысячи раз в секунду?
Re: Ускоренная версия функции определения високосного года
Добавлено: 16.12.2025 08:10:56
Alexander
Даже если функция используется один раз в секунду - это выигрыш, а не проигрыш. Процессор-то при этом отдыхает. А где-то и большие данные обрабатываются на эту тему - функция на самом часто используемая. Каждая ускоренная в два раза функция либо удваивает мощность процессора, либо уполовинивает энергопотребление компьютера - как на это смотреть.
Пользователи, кстати, могут здесь написать, насколько она улучшила их программы.
Re: Ускоренная версия функции определения високосного года
Добавлено: 16.12.2025 09:44:53
Снег Север
Да мне не жалко, программисты развлекаются. Но вот насчет частого использования, да ещё в приложениях, а не серверами - это как-то сомнительно.
Re: Ускоренная версия функции определения високосного года
Добавлено: 17.12.2025 09:32:33
iskander
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.
Re: Ускоренная версия функции определения високосного года
Добавлено: 21.12.2025 20:56:11
Alexander
Интересный во всех отношениях тест. Спасибо! И то, что в транке это добавили - отлично. Будем ждать релиза.