|
Опубликовано 19.05.2006 14:04 (19 лет назад) # |
Помню вроде бы на ДМе была веточка. Или где то еще.
Короче смысл таков. Выкладывайте сюда то, что есть у вас.
Не большие шустрые полезные процедурки.
Любые, которые могут пригодиться. Оптимизированные.
Если не жалко конечно.
Вот к примеру есть функция вычисления синуса/косинуса. В System.pas.
У кого нить есть аналог, но чтобы пошустрее?
Я не говорю, что те медленные, но просто.. чисто из интереса. У меня не получилось сделать. Если это не реально - другое дело. Я просто точно не знаю.
Ну это так.. для затравки.
редакция от DeadMeat, 19.05.2006 14:05 |
|
|
Древний организм
|
Опубликовано 19.05.2006 14:14 (19 лет назад) # |
Помнится я выкладывал чертовски шуструю процедуру, для вычисления ближайшего БОЛЬШЕГО (либо равного) n-битного числа (2, 4, 8, 16, 32... и т.д.) к указанному.
пример: 33 = 64; 256 = 256; 500 = 512 и так далее.
Function NormalizeSize(int : integer) : integer;
asm
bsr ecx, eax
mov edx, 2
add eax, eax
shl edx, cl
cmp eax, edx
jne @ne
shr edx, 1
@ne :
mov eax, edx
end;
Выполняется за оч. маленькое кол-во тактов, ибо оптимизирована по самое нехочу :) Применение различно. Например если есть текстура како-то разрешения, а для правильности надо ее догнать до степени двойки, то этой процедурой легко вычислить правильную размерность для новой текстуры. Другие применения думаю и сами найдете без лишних проблем. Оптимизировал чисто для интереса, так как надобности в скоростией этой процедуры не было. Размер передаваемого значения не влияет на скорость выполнения.
редакция от Darthman, 19.05.2006 14:25 |
|
|
|
Опубликовано 19.05.2006 16:22 (19 лет назад) # |
DeadMeat, с каких пор ты об оптимизации стал думать? Кто тебя так обидел? ;)
procedure SinCos(const Theta: Extended; var Sin, Cos: Extended);
asm
FLD Theta
FSINCOS
FSTP tbyte ptr [edx] // Cos
FSTP tbyte ptr [eax] // Sin
FWAIT
end; |
|
|
|
Опубликовано 21.05.2006 11:56 (19 лет назад) # |
XProger,
Я просил чтото свое, а не содержимое стандартных модулей....
редакция от DeadMeat, 21.05.2006 11:57 |
|
|
|
Опубликовано 21.05.2006 16:14 (19 лет назад) # |
а вдруг в стандартных модулях - его? :) |
|
|
|
Опубликовано 29.05.2006 11:57 (18 лет назад) # |
Мда... Просмотров дофига, а постов всего 4.
Жаль.. |
|
|
|
Опубликовано 20.11.2006 16:19 (18 лет назад) # |
function NextPowerOfTwo(Value: Integer): Integer;
begin
Result:= 1;
asm
xor ecx, ecx
bsr ecx, Value
inc ecx
shl Result, cl
end;
end;
Во, работать не быстрее будет? (Я не знаю, она не моя)
Кстати для синусов и косинусов можно юзать хеш-таблицы...
редакция от CHASER, 20.11.2006 16:21 |
|
|
Древний организм
|
Опубликовано 20.11.2006 16:40 (18 лет назад) # |
Нет, ибо оно дает следующее число степени двойки. представленная мной процедура приводит ближайшее большее число равное степени двойки. Тоесть работает с любыми числами.
А по вопросу - да быстрее работает :) но не так. |
|
|
|
Опубликовано 20.11.2006 16:50 (18 лет назад) # |
function NextPowerOfTwo(Value: Integer): Integer;
begin
Result:= 1;
asm
xor ecx, ecx
bsr ecx, Value
inc ecx
shl Result, cl
end;
end;
//---------------------------------------------------------------------------
function IsPowerOfTwo(Value: Integer): Boolean;
begin
Result:= (Value >= 1) and ((Value and (Value - 1)) = 0);
end;
//---------------------------------------------------------------------------
function CeilPowerOfTwo(Value: Integer): Integer; register;
asm
xor eax, eax
dec ecx
bsr ecx, ecx
cmovz ecx, eax
setnz al
inc eax
shl eax, cl
end;
//---------------------------------------------------------------------------
function FloorPowerOfTwo(Value: Integer): Integer;
asm
xor eax, eax
bsr ecx, ecx
setnz al
shl eax, cl
end;
Вот, все что есть. (ЗЫ. Это из исходников Asphyre)
редакция от CHASER, 20.11.2006 16:51 |
|
|
Древний организм
|
Опубликовано 20.11.2006 18:11 (18 лет назад) # |
Понятно. Лайфповер маньяк :) |
|
|
|
Опубликовано 20.11.2006 19:11 (18 лет назад) # |
Кстати, можешь обьяснить, то делает bsr? |
|
|
|
Опубликовано 28.11.2006 15:56 (18 лет назад) # |
Из стандартных финкций(может кто не знает):
function Hypot(const X, Y: Extended): Extended; - длина гипотенузы правильного треугольника или же длина вектора.
Это вместо: Sqrt(Sqr(x) + Sqr(y));
редакция от 2morrowMan, 28.11.2006 15:57 |
|
|
Древний организм
|
Опубликовано 28.11.2006 16:20 (18 лет назад) # |
CHASER дает разрядность числа в двоичной системе. |
|
|
|
Опубликовано 09.09.2008 11:21 (16 лет назад) # |
DeadMeat написал:
Вот к примеру есть функция вычисления синуса/косинуса. В System.pas.
У кого нить есть аналог, но чтобы пошустрее?
Ну это так.. для затравки.
CHASER правильно сказал. Самое оптимальное - ХЭШ-таблицы, но потеря точности. Чем больше ХЭШ-таблица, тем выше точность, но появляется overhead на сбоях кэша. Второй вариант ускорения синуса и косинуса - разложить в ряд. Чем больше членов ряда используешь в сумме, тем точнее результат. Но, имхо, в таком случае получить приемлемую точность за более короткое время (чем уже есть в system.pas) имхо нереально (надо погонять, потестировать)...
Сорри за некрофильство, не мог пройти мимо ;)
редакция от Spirit, 09.09.2008 11:26 |
|
|
|
Опубликовано 09.09.2008 12:45 (16 лет назад) # |
Дай ка тоже вфигачу свои пять копеек))
const
_p180 : extended = 3.14159265358979323846264 / 180;
_180p : extended = 180 / 3.14159265358979323846264;
function Pi : extended; inline(
$D9/$EB { fldpi }
);
function E : extended; inline(
$D9/$E8/ { fld1 }
$D9/$EA/ { fldl2e }
$D8/$E1/ { fsub st,st(1) }
$D9/$F0/ { f2xm1 }
$D9/$C9/ { fxch }
$DC/$C1/ { fadd st(1),st }
$D8/$C0/ { fadd st,st }
$DE/$C9 { fmulp }
);
function Tan(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$F2/ { fptan }
$83/$C4/$08/ { add sp,8 }
$DD/$D8 { fstp st }
);
{ àíàëîãè÷íî òàíãåíñó Tan(a), íî âåëè÷èíà â ãðàäóñàõ }
function GTan(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$DB/$2E/_p180/ { fld tbyte ptr [_p180] }
$36/$DC/$0F/ { fmul qword ptr ss:[bx] }
$D9/$F2/ { fptan }
$83/$C4/$08/ { add sp,8 }
$DD/$D8 { fstp st }
);
function ArcTan(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$E8/ { fld1 }
$83/$C4/$08/ { add sp,8 }
$D9/$F3 { fpatan }
);
function GArcTan(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$E8/ { fld1 }
$83/$C4/$08/ { add sp,8 }
$D9/$F3/ { fpatan }
$DB/$2E/_180p/ { fld tbyte ptr [_180p] }
$DC/$C9/ { fmul qword ptr ss:[bx] }
$DD/$C0/
$D9/$F7
);
function Sin(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$FE/ { fsin }
$83/$C4/$08 { add sp,8 }
);
function GSin(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$DB/$2E/_p180/ { fld tbyte ptr [_p180] }
$36/$DC/$0F/ { fmul qword ptr ss:[bx] }
$D9/$FE/ { fsin }
$83/$C4/$08 { add sp,8 }
);
function Cos(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$FF/ { fcos }
$83/$C4/$08 { add sp,8 }
);
function GCos(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$DB/$2E/_p180/ { fld tbyte ptr [_p180] }
$36/$DC/$0F/ { fmul qword ptr ss:[bx] }
$D9/$FF/ { fcos }
$83/$C4/$08 { add sp,8 }
);
function Ln(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$D9/$ED/ { fldln2 }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$F1/ { fyl2x }
$83/$C4/$08 { add sp,8 }
);
function Log(a : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$D9/$EC/ { fldlg2 }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$F1/ { fyl2x }
$83/$C4/$08 { add sp,8 }
);
{ ëîãàðèôì ÷èñëà Y ïî îñíîâàíèþ X }
function LogX(y,x : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$D9/$E8/ { fld1 }
$D9/$E8/ { fld1 }
$36/$DD/$47/$08/ { fld qword ptr ss:[bx+8] }
$D9/$F1/ { fyl2x }
$DE/$F9/ { fdivp }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$F1/ { fyl2x }
$83/$C4/$10 { add sp,16 }
);
{ Ðàáîòàåò êîððåêòíî äî X <= 0.8 }
function SmallExp(x : double) : double; inline(
$8B/$DC/ { mov bx,sp }
$D9/$E8/ { fld1 }
$36/$DD/$07/ { fld qword ptr ss:[bx] }
$D9/$EA/ { fldl2e }
$83/$C4/$08/ { add sp,8 }
$DE/$C9/ { fmulp }
$D9/$F0/ { f2xm1 }
$DE/$C1 { faddp }
);
{ åñëè áèò BitNum óñòàíîâëåí, âîçâðàùàåò TRUE }
function Bit(x : longint; BitNum : word) : wordbool; inline(
$59/ { pop cx }
$66/$5B/ { pop ebx }
$66/$33/$C0/ { xor eax,eax }
$FE/$C0/ { inc al }
$66/$D3/$E0/ { shl eax,cl }
$66/$23/$C3/ { and eax,ebx }
$66/$D3/$E8 { shr eax,cl }
); |
|
|
|
Опубликовано 09.09.2008 17:55 (16 лет назад) # |
Gambit_oz и каким макаром этот чудо код компилируется? |
|
|
|
Опубликовано 09.09.2008 20:57 (16 лет назад) # |
Компилируется как инлайн код. По крайней мере в Turbo/Borland Pascal такое компилировалось. Не знаю, как в Delphi/BDS...
По быстродействию выигрыш совсем небольшой, только за счет исключения вызова подпрограмм (манипуляции со стековыми фреймами можно исключить и без инлайна). |
|
|
|
Опубликовано 10.09.2008 06:09 (16 лет назад) # |
да спирит прав, для паскаля сия библиотека была написана, в дельфи надо просто инлайны отрубить
на счет скорости выигрыш есть раза в 2
например
function Tan(a : double) : double;
asm
mov bx,sp
fld qword ptr ss:[bx]
fptan
add sp,8
fstp st
end; |
|
|
|
Опубликовано 10.09.2008 16:30 (16 лет назад) # |
2 Gambit_oz:
выигрышь в два раза - не совсем корректно считаете. Для начала добавьте директиву assembler:
function Tan(a : double) : double; assembler;
asm
mov bx,sp
fld qword ptr ss:[bx]
fptan
add sp,8
fstp st
end;
Это исключит генерацию пролога и эпилога функции. Теперь разница по скорости должна быть немного меньше. Проверить можно по сгенерированному коду. И потом, большая зависимость от используемого процессора (размер кэша).
редакция от Spirit, 10.09.2008 16:35 |
|
|