![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Sin Cos [Delphi]
zxcxz © (2006-06-15 20:47:00)Слышал что функции sin и cos очень тормозные. В игровом приложении каждый кадр нуждается в вычислении большого количества значений от этих функций. Кто знает на сколько эти функции тормозят работу игрового приложения? И рациональнее ли заменить эти функции на выбор процедурой case of приблизительного значения из таблицы синусов и косинусов?
Megabyte-CeerCop (2006-11-02 12:26:00) [21]Я какраз три дня назад собрался заменять в своем движке все синусы на таблицы, но после небольшого теста понял что не стоит.
1) в цикле 10000000 итерации выщитывал синус заняло на глаз 2 сек.
2) в цикле 10000000 итерации из массива в 1000 элементов выбирал значение и прибавлял к переменной. зпняло 1.5 сек...
а если к этому добавить время на определение позиции в массиве.. прироста не будет точно.
@!!ex (2006-11-02 11:44:00) [22]
> Rial © (01.11.06 23:18) [20]
Смотря при какой дискретности. ;)
Сергей М. (2006-11-02 11:36:00) [23]
> zxcxz © (15.06.06 20:47)
Современные высокопроизводительные игровые (и не только) приложения используют на полную мощь MMX/XMM/SSE/SSE2/SSE3/3DNow-расширения системы команд CPU.
А то о чем ты говоришь - это каменный век, в любом из рассматриваемых тобой вариантов.
Shirson (2006-11-02 09:04:00) [24]XProger, попробую. Просто для моих нужд точности в 0.1° хватало с избытком.
Кстати, Тимур, хотел тебе пару вопросов по твоему движку задать, а у тебя аська в оффлайне беспрерывно. Или ты номер сменил, или шифруешься? :)
DeadMeat (2006-11-02 08:52:00) [25]Так никто мой вариант и не оттестил... Его кстати желательно компилить с inline'ом.
XProger (2006-11-02 08:46:00) [26]Shirson, делай выборку из массива 360 000 значений...
Shirson (2006-11-02 08:29:00) [27]Замерял буквально дня два назад.
Скорость получения синуса / косинуса из функции приблизительно в 3.5 раза медленее, чем выборка из массива преподсчёта (3600 значений).
Выбор осуществлялся не на прямую, а с предварительным контролем и обработкой. Т.е. условно, угол в 500г переводился в 140г.
Rial (2006-11-01 23:18:00) [28]> [19] @!!ex © (01.11.06 21:05)
>
> > XProger © (01.11.06 20:49) [17]
>
> Так о дискретности никто не говорил. :))
> ВОпрос ыл: ыстрее или нет, :))
Ответ - не быстрее.
@!!ex (2006-11-01 21:05:00) [29]
> XProger © (01.11.06 20:49) [17]
Так о дискретности никто не говорил. :))
ВОпрос ыл: ыстрее или нет, :))
> Ketmar © (01.11.06 20:55) [18]
Согласен. Возможно не прав.
Ketmar (2006-11-01 20:55:00) [30]>[16] @!!ex(c) 1-Nov-2006, 20:29
>Хм. Что за странные споры?
>Таблица быстрее.
да? ты уверен? учитывая, что в DooM не использовали сопроцессор. а теперь помедитируй над скоростью теперешних сопров и над размерами таблицы, которая засоряет собой кэш.
XProger (2006-11-01 20:49:00) [31]@!!ex, какая там дискретность прицеливания в думе была? Вот-вот... сейчас во времена сверхчувствительных мышей со снайперки стрелять любят многие ;)
sin/cos считать быстрее во время исполнения (в большинстве случаев)
O-lysy, 0,61566147532565827966881109284366
@!!ex (2006-11-01 20:29:00) [32]Хм. Что за странные споры?
Таблица быстрее.
Это доказали id когда делали первый Дум.
Насколько мне известно в то время народ активно доказывал, что такую игру НЕЛЬЗЯ сделать на существующих системах...
И сидели в ступоре когда видели дум....
Дум как раз и использовал заранее просчитанные значения синусов косиносув....
Чем не доказательство, что это быстрее? :))
O-lysy (2006-11-01 20:23:00) [33]подскажите sin 38?
Tsmar (2006-06-18 00:32:00) [34]Rial ©
вот это мороз...
Rial (2006-06-17 17:09:00) [35]И при каждом вызове читать из файла, предварительно вычислив позицию. :)
RzCoDer (2006-06-17 12:33:00) [36]
> эта функция вызывается один раз при старте и все.
Можно в обще однажды просчитать и записать всё это в файл ;)
DeadMeat (2006-06-16 15:35:00) [37]Я думаю это не особо критично, учитывая, что эта функция вызывается один раз при старте и все.
Вообще.. если есть возможность, не могли бы вы оттестировать эту байду на скорость и точность (при определенном шаге конечно).
XProger (2006-06-16 14:48:00) [38]DeadMeat, функцию создания таблиц можно ооочень хорошо оптимизировать зная одну аксиому тригонометрии sin(a) = cos(a + pi/2).
Cash (2006-06-16 12:57:00) [39]Умные дядьки говорят, что если для алгоритма БПФ (Быстрое
преобразование Фурье) предусмотреть таблицу синусов и косинусов, то
накладность алгоритма снижается в десятки раз, а в отдельных случаях
(таких много) - в сотни... Но это БПФ, а что у товарища автора - неизвестно...
(Кто знает и делал БПФ, поймут меня... :) )
zxcxz, попробуй всетаки обойтись с таблицей синусов и косинусов.
Порекомендовал бы динамическое вычисление таблиц, но не знаю что там
за проблема такая...
DeadMeat (2006-06-16 09:25:00) [40]На оригинальность и супер скорость не претендую, но по моим тестам и для моей ситуации работает шустрее:
var
tb_COS: array of single;
tb_SIN: array of single;
tb_TAN: array of single;
bufang: cardinal;
AngleStep: cardinal;
tb_SIZE: cardinal;
function Cos_rn (const X: single): single;
asm
FLD X
FCOS
FWAIT
end;
function Sin_rn (const X: single): single;
asm
FLD X
FSIN
FWAIT
end;
function Tan_rn (const X: single): single;
asm
FLD X
FPTAN
FSTP ST(0)
FWAIT
end;
procedure PrepareAnglesTable (step: cardinal);
var
i: cardinal;
rad: single;
buflen: cardinal;
counter: double;
bufrad: single;
steper: single;
begin
AngleStep := step;
buflen := 360 * step;
tb_SIZE := buflen;
SetLength (tb_SIN, buflen);
SetLength (tb_COS, buflen);
SetLength (tb_TAN, buflen);
steper := 1 / step;
counter := 0;
bufrad := pi / 180;
for i := 0 to buflen - 1 do
begin
rad := bufrad * counter;
tb_SIN[i] := Sin_rn (rad);
tb_COS[i] := Cos_rn (rad);
tb_TAN[i] := Tan_rn (rad / 2);
counter := counter + steper;
end;
end;
function GetIndexFromAngle (angle: single): cardinal;
begin
result := round ((tb_SIZE * cardinal (angle < 0)) + angle * AngleStep) mod tb_SIZE;
end;
function ghCos (angle: single): single;
begin
result := tb_COS[GetIndexFromAngle (angle)];
end;
function ghSin (angle: single): single;
begin
result := tb_SIN[GetIndexFromAngle (angle)];
end;
function ghTan (angle: single): single;
begin
result := tb_TAN[GetIndexFromAngle (angle)];
end;
procedure ghSinCosTan (const angle: single; var sin, cos, tan: single);
begin
bufang := GetIndexFromAngle (angle);
sin := tb_SIN [bufang];
cos := tb_COS [bufang];
tan := tb_TAN [bufang];
end;
procedure ghSinCos (const angle: single; var sin, cos: single);
begin
bufang := GetIndexFromAngle (angle);
sin := tb_SIN [bufang];
cos := tb_COS [bufang];
end;
Готовится так:
- в начале вызываемPrepareAnglesTable (...)с параметром ШАГ, который означает нашу "точность". Т.е. к примеру вызываем с 1000, получаем шаг сетки в 1/1000 = 0.001
- а потом уже можно вызывать функции вычисления (ghSinCosTan, ghSinCos, ghTan, ghSin, ghCos - остальные это внутренние)
При простом тесте, вычислений всех трех углов в цикле, эта шняга работала быстрее. А вот при вытаскивании только одного, не могу сказать.
Если найдете ошибки, сообщите, т.к. до зверской оптимизации пока руки не дошли.
З.Ы. Углы передаются в градусах (0...360). Можно и отрицательные, можно и дробные в зависимости от шага. Если в шаг не попадают, берется ближайшее значение.