Поплавок, подвійний або обидва для 2D-класу вектор?


11

Зараз я пишу невеликий кросплатформенний 2-ігровий движок на основі OpenGL для нашої студії. Коли я досліджував, який 2D-клас вектор використовувати, я натрапив на три різні парадигми дизайну:

  • Float & Call-by value, як у цій статті про Gamasutra . Здається, це швидко, але пропонує невелику точність (див. Також цю нитку ). Pro: Швидкий, портативний та сумісний з більшістю бібліотек.

  • Подвійний та заклик за посиланням. Якщо я правильно розумію вищевказану статтю, я можу також використовувати 2 змінні з подвійною точністю замість 4 плаваючих чисел. Відповідно до вищезазначеного потоку подвійний все-таки повільніше, ніж плаваючий.

  • Шаблон для double та float: У широко популярній книзі " Архітектура ігрових двигунів " використовуються шаблони, що дозволяють використовувати float та double за потребою. Очевидним недоліком є ​​роздуття коду. Крім того, я сумніваюся, що код можна оптимізувати, в основному не записуючи два класи, все одно.

Буду вдячний дізнатись, які рішення ви використовуєте в своїх власних двигунах і наскільки точні, наприклад, популярні ігрові двигуни, тож я можу вирішити, яке рішення я впроваджуватиму в нашому двигуні. На даний момент я думаю про те, щоб просто використовувати поплавкову точність і жити з нею.


Повільніше куди ? Ви не можете говорити про швидкість, якщо вона не пов'язана з певною архітектурою.
o0 '.

2
@ Lo'oris: Я не знаю жодної архітектури, де подвійне швидше, ніж плаваюче.

Замість того, щоб писати власний векторний клас, подумайте про використання Sony ( bulletphysics.org/Bullet/phpBB3/… ). Це легка "бібліотека", що випадає лише в заголовку, яка вже мікрооптимізована, і всі бібліотеки векторів в основному є тим же самим зовнішнім інтерфейсом.

@Joe: 2 парні замість 4 поплавків?
o0 '.

@ Lo'oris: Питання сформульовано трохи дивно, я не знаю, чи запитувач розгублений чи просто ви - ви використовуєте два парних "замість" чотирьох плавців при роботі з SIMD, оскільки реєстр шириною 128 біт. Вам ще потрібно обробити рівну кількість чисел, і ви робите це на півшвидкості.

Відповіді:


9

Я завжди використовую float, якщо у мене немає причин використовувати double, наскільки я використовую int, якщо у мене немає причин використовувати int64_t.

Поплавці не мають жодних проблем робити точну цілу арифметику до 2 24 , чого саме більшість людей (в основному нераціонально) бояться. Подвійні не вирішують проблему того, що загальні значення точно не представляються - незалежно від того, отримаєте ви 0,10000001 або 0,10000000000000001, ви все ж повинні переконатися, що ваш код вважає його "рівним" 0,09999999.

Парові повільніші на кожній платформі, ви дбаєте про те, щоб писати ігри, займете вдвічі більше пропускної здатності пам’яті та матимете менше спеціалізованих інструкцій щодо процесора.

Одноточні поплавці залишаються стандартом для апаратних графічних інтерфейсів, як на стороні C / C ++, так і всередині шейдерів.

Напевно, вам знадобиться подвійний вектор в якийсь момент, але його слід використовувати при необхідності, а не за замовчуванням.

Що стосується шаблонування - ви праві, для досягнення максимальної продуктивності ви хочете все-таки спеціалізувати шаблони вручну. Окрім цього, я провів кілька тестів на якийсь шаблонний код у вихідні дні (зробивши 4-ple IntRect та FloatRect), і виявив, що шаблонна версія займає приблизно 20 разів довше, ніж просто повторити код, який склав близько 15 рядків . Повторення смокче, але очікування компіляції смокче більше - і це не так, як мені колись знадобиться StringRect або FooRect.


" Парний бік повільніше на кожній платформі […] " - Потрібне цитування.
зеніт

3

У рамках ігрової системи Microsoft XNA є клас Vector2, який використовує поплавці. Це була б моя найбільша особиста причина, коли я ходив з поплавками, тому що я довіряю мудрості та досвіду команди XNA набагато більше, ніж моїй власній.

Мені було досить цікаво прочитати відповідь у цьому питанні щодо переповнення стека: "Float vs Double Performance" . Також є нитка gamedev.net з деякою дискусією про подвійну продуктивність у графічних процесорах. Я вважаю, що можна припустити, що парні - повільніше, ніж плаваючі, принаймні у багатьох графічних процесорах, і я особисто завжди використовував функції floGL OpenGL над своїми подвійними аналогами. Це може не застосовуватись сьогодні, але якщо ви вважаєте, що не кожен, хто працює з вашою грою, має найновіший графічний процесор з вбудованою подвійною підтримкою, я вважаю, що це достатньо підстав для використання float та отримання додаткової бітковини.


1
З питання ТА: "Принаймні, на процесорах x86 плаваючі та подвійні перетворюються FPU на 10-байт-реальну для обробки". Хоча це правда, вона нехтує як інструкціями SIMD, так і додатковими вимогами пам’яті (= гірша когерентність кешу, більша пропускна здатність пам’яті) удвічі, обидва вони продовжують робити це повільніше, ніж плавати в реальних тестах.

Я порахував, що є улов. Ви повинні прокоментувати це на відповідь ТА, я б його схвалив.
Ricket

Це вже є коментар.

1
Оскільки ви вивели XNA, я можу також зазначити, що Direct2D також використовує одноточні поплавці.
Майк Стробель

А для повноти OpenGL має плаваючі та подвійні версії своїх методів, тому в цьому сенсі вона є нейтральною.
Рікет
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.