Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Sin Cos [Delphi]


Страницы:   1 2 3

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). Можно и отрицательные, можно и дробные в зависимости от шага. Если в шаг не попадают, берется ближайшее значение.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо