Чи насправді Big O має значення?


17

У найгіршому випадку Big O викладають над усім іншим. Порівняно зі складністю простору, звичайним аналізом випадку, простотою над складністю тощо.

Зокрема, для ігрового програмування та промисловості, що насправді найбільше важливо і чому?

Довідка була б дуже корисною.


Big-O = Оптимізація. Взяв мене трохи, щоб зрозуміти, що таке великий 0.
AttackingHobo

12
Big-O - це не «оптимізація». Big-O - це форма аналізу, яка розповідає про те, як будуть вести себе різні алгоритми з точки зору ефективності, оскільки кількість елементів, що діяли при збільшенні. Докладніше див. En.wikipedia.org/wiki/Big_O_notation .
ZorbaTHut

2
Можу запевнити вас, люди, які придумали октриси, і BSP / PVS знали все про big-O. Зрештою, єдине, що має значення, - це ефективність програми. Але щоб потрапити туди, потрібно враховувати всі речі, включаючи асимптотичну складність алгоритмів, які обробляють багато даних.
drxzcl

1
Запам’ятайте правило, коли оптимізувати: 1) Не робіть цього. 2) (лише для експертів) Не робіть цього ще.
zaratustra

Перш за все, Big O можна використовувати для простору або обчислювальної складності, тому "над усім іншим" не зовсім так. По-друге, Big O, як правило, набагато простіше обчислити щось, ніж звичайний аналіз випадку, і він би використовувався як швидка психічна перевірка на те, чи ви робите щось не так. Якщо малювання спрайту займає час O (2 ^ n), ви, ймовірно, повинні вибрати інший алгоритм. Якщо ви хочете більш практичний підхід до розробки програмного забезпечення, погляньте на практику SE, а не на CS. КС теоретичний за своєю суттю, тоді як ПП більше базується на галузі.
Делетер

Відповіді:


25

Як і будь-яке інше питання щодо "що таке єдиний вірний шлях", це всі інструменти у вашій панелі інструментів, і є випадки, коли big-O перетворює все, і місця, де це не має значення (тм).

Ви б ніколи не писали вирішувач фізики, не переймаючись великим O. Ви б не реалізували алгоритм сортування (для будь-якого, але найменшого набору даних), не турбуючись про це. Якщо ви пишете мережеву гру, ви будете перейматися способом ефективності та масштабами мережевого трафіку на користувача.

Ви, можливо, не так переймаєтесь великим O, коли, ну, я не можу реально придумати час, але я впевнений, що є такі. :) На щастя, більшість речей, які ми робимо в іграх, змінюються лінійно; Ви хочете прочитати файл з диска? Знадобиться кількість часу, лінійно пропорційна розміру файлу (дисконтування постійного фактора пошуку та можливих наслідків розміру сектору).

Однак що робити, якщо ви хочете знайти конкретну сутність у списку сутностей? Це лінійний пошук кожного разу, коли ви це робите. Якщо вам потрібно один раз знайти гравця для кожної сутності у світі, такий підхід вб'є вас для всіх, крім самих тривіальних ігор, і навіть тоді, мабуть, варто "оптимізувати" цей пошук постійним часом (наприклад, зберігати з індексу або вказівник на гравця десь), що дає вам більше часу на виконання інших речей, які насправді видно гравцеві.

Я думаю, що це підсумовує; щоразу, коли процесор робить щось, що не є безпосередньо представним для програвача, він витрачає час. Максимізація часу, в який процесор обчислює дані, які будуть показані гравцеві, - це максимальне використання WOW! ви даєте гравця.


8
Це. Важливо зрозуміти характеристики продуктивності вашого коду. Ви ніколи не знаєте, коли дизайнер буде використовувати щось, що ви додали, таким чином, якого ви не очікували, і раптом біт коду, який, на вашу думку, доведеться обробляти лише 5 предметами, зараз обробляє 5000 та пінг пінг 100 разів. Ви це оптимізуєте? Ти можеш? Скільки насправді розумно? Профіль підкаже лише те, наскільки це повільно, а не чому. Знаючи складність, ви підкажете, чи потрібно оптимізувати код, або замінити його чимось іншим.
JasonD

3
Домовились. Університети навчають вас "Big-O", оскільки він вирішує багато проблем, з якими ви зіткнетесь. Коли вас запитують «о, ми можемо зробити це нескінченним, а не лише 5? тестери ненавидять обмеження - саме тоді навчання окупається. Ви не повинні просто говорити "ні, я не можу". Важливо мати можливість вирішити проблему і сказати «так, я можу». Вашій грі потрібна галактика для пошуку? 'Без проблем'. Ці мільйони одиниць потрібно замовити? 'Без проблем'. "Не вивчив цього достатньо", просто не скорочує.
Rushyo

Msgstr "Можливо, ви не настільки стурбовані великим O, коли ..." обробляйте вхідні ключі. Я успадкував систему введення, яка перейшла до тривалості, щоб вирішувати відображення ключів> дій в постійний час, використовуючи таблицю пошуку. Переключення його на лінійний пошук масиву пар (клавіш, дії) зберегло пам'ять і не вплинуло на продуктивність, оскільки користувачі рідко натискають на кадр більше декількох клавіш, а масив зазвичай становить лише 20-30 елементів. Це також дозволить додати (клавіша, клавіша, дія) для акордів.

Джо, звичайно, хоча це стосується різного роду. Ви хочете O (1), де постійний коефіцієнт високий, або O (n) з малим 'n' та низьким постійним коефіцієнтом? Знання big-O в цьому випадку не є проблемою, але може допомогти вам розібратися, чи рішення має сенс для обставин, в яких воно буде використовуватися.
Даш-Том-Банг

13

Моє правило полягає в тому, що, якщо ви не O (страшно), ваші інші проблеми є більш доречними.

Моє інше правило: дані є суттєвими. Якщо ви не профіліруєте свій код реалістичним набором даних, ви просто здогадуєтесь.

Редагувати: Щоб детальніше розібратися, ваш великий O не є таким важливим, оскільки (принаймні, на мій досвід) більшість ваших наборів даних відносно крихітні. Вам, мабуть, не важливо верхня межа продуктивності, коли ви працюєте зі структурою даних з меншою кількістю декількох сотень елементів. І якщо у ваших списках є 100k + елементів, то вам дійсно потрібно враховувати всі аспекти ваших алгоритмів. Це, і з мого досвіду, пам'ять є скоріше обмежуючим фактором, ніж швидкість процесора. Більш швидкий алгоритм випрямлення пам'яті може бути не таким хорошим, як швидше, але повільніше, залежно від випадків використання.


8

Великий O має велике значення в більшості випадків, але іноді, очевидно, «гірший» алгоритм в теорії виявляється набагато швидшим на практиці.

Ознайомтеся з чудовим прикладом від Тоні Альбрехта: http://seven-degrees-of-freedom.blogspot.com/2010/07/question-of-sorts.html

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

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

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


"Проблема з Big O" полягає в тому, що люди, здається, забувають, що це алгоритмічна складність продуктивності wrt щодо великих розмірів набору даних. В іграх ми (як правило) не вражаємо ці значення N, тому нам потрібно турбуватися про інші частини головоломки. Я підозрюю, що сортування бульбашок завжди буде перевершувати швидкий вибір, коли у вас є список з двох елементів.
Даш-Том-Банг

7

Коли я кодування в движку, я часто стосується тільки з фіксованим n: Я вже отримав розділ просторового обмежує число об'єктів прийому update(), physics()іrender() приблизно тих , хто на екрані і прилеглих районах. Максимальний розмір партії зазвичай досить чітко визначений за гру, хоча він незмінно трохи більший, ніж ви планували.

У цьому випадку я не так переймаюся великим O, як мене турбує коефіцієнт множника постійного коефіцієнта та умови нижчого порядку. Для такої функції, як час виконання a*n^2 + b*n + c(який є O(n^2)), я часто набагато більше займаюся скороченням aта, можливо, усуненням c. Вартість налаштування або відмови cможе стати пропорційно великою порівняно з невеликою n.

Однак це не означає, що big-O (або, особливо, big-theta ) - чудовий індикатор кодового запаху. Побачити O(n^4)десь або ще гірше O(k^n)геометричний час, і саме час переконатися, що ви розглядаєте інші варіанти.

Я, як правило, набагато більше стурбований оптимальністю big-O і стрибанням через обручі, щоб знайти алгоритми з нижчим big-O, коли я маю справу з інструментами створення даних. Незважаючи на те, що кількість об'єктів у заданому рівні / потоковій області загалом чітко визначена, загальна кількість об'єктів / арт-об’єктів / файлів конфігурації / тощо у всій грі може бути. Це також набагато більша кількість. Навіть запускаючи паралельні дані, ми все одно чекаємо на порядок хвилини (я знаю, скупотіння - дані для консолей можуть зайняти години - ми в основному невеликі портативні ігри), щоб пройти jam data-clean && jam dataцикл.

Щоб навести конкретний приклад: це дійсно вийшло з ладу за допомогою алгоритму фонового потокового потоку фонових зображень, який передає плитки 8х8 256 кольорів. Корисно ділитися буферами потокового потоку між фоновими "шарами", і ми можемо мати до 6 із них на заданому рівні, що розділяє один і той же буфер. Проблема полягає в тому, що оцінка розміру потрібного буфера ґрунтується на можливих позиціях усіх 6 шарів - і якщо вони є простою кількістю ширини / висоти / швидкості прокрутки, ви швидко приступаєте до вичерпного пошуку - який починає наближатисяO(6^numTiles)- який у багатьох випадках знаходиться у категорії "довше, ніж буде Всесвіт". На щастя, більшість випадків - це лише 2-3 шари, але навіть тоді ми перевищуємо півгодини часу виконання. На даний момент ми вибираємо дуже малий підмножина цих можливостей, збільшуючи деталізацію до тих пір, поки не пройде задана кількість часу (або ми не виконали завдання, що може статися для невеликих двошарових конфігурацій). Ми трохи збільшимо цю оцінку на основі попередньої статистики того, як часто ми виявились неправильно, а потім додамо трохи додаткової накладки для гарної міри.

Ще один цікавий приклад: на комп'ютерній грі, провідний інженер деякий час експериментував із пропускними списками . Накладні витрати на пам'ять закінчуються тим, що спричиняють більше ефектів кешу, що додає свого роду непостійний множник у всій справі - тому вони насправді не є малим вибором для малих n. Але для великих сортованих списків, де пошуки часті, вони дають перевагу.

(Я часто знаходжу, що алгоритм наївності вищий з великим розміром O, швидше на менших наборах даних і простіший для розуміння; тим цікавіші / складніші (наприклад, патріція трие) людям важче зрозуміти і підтримувати, але більш висока продуктивність на більших набори даних.)


4

Це може бути зручно, але це також може бути неактуально. Візьмемо, наприклад, мою останню гру, яка є чимось клоном Smash TV. Гра зверху вниз, монстри заливаються з боків, ви стріляєте в них.

Зараз існує маса розумних способів визначення зіткнень. Ви можете використовувати KDtrees, щоб розділити простір, щоб ви не випробовували кулі на монстрів, на які вони не могли потрапити. І, звичайно, я міг бути розумним, і міг би це зробити.

Але я відчував себе лінивим, тому просто порівняв кожну кулю проти кожного монстра. Навіть у найжорстокіших ситуаціях код зіткнення використовував набагато менше 10% ігрового процесора зі швидкістю 60 кадрів в секунду. Big-O: Неважливо.

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

Big-O так само важливий в іграх, як і у всьому іншому: тобто зовсім неважливо, аж до того, як він стане критичним.

Ідіть, напишіть якийсь код. Якщо це занадто повільно, тоді профілюйте його.


3

Аналіз Big-O важливий, але це не перше, про що варто задуматися при розробці ігор. Оскільки створення ігор передбачало багато складного коду, я завжди рекомендував Code Simplicity як перший критерій алгоритму. Алгоритми зі складним веденням бухгалтерського обліку просто витрачають ваш час.

Я думаю, що дуже важливо, щоб ваша гра завжди працювала зі швидкістю 60 кадрів в секунду під час розробки. Коли ви зануритесь нижче цього, перше, що вам потрібно зробити, це запустити профілер. Як тільки ви знайдете вузьке місце, ви нападаєте на нього. Багато часу потрібно робити, щоб не кодувати речі, наприклад, скажіть дизайнерам рівнів, щоб помістити менше матеріалів у певну область (і надати їм інструменти для цього).

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

  1. Переконайтеся, що ви не називаєте новий кадр або не називаєте кожен кадр (це завжди проблема №1)
  2. Скоротіть роботу: менше рейсів, менше хлопців тощо.
  3. Проблеми типу алгоритму Big-O
  4. Когерентність кеш-пам'яті: вкладайте матеріали в масиви, а не в розсіяну пам'ять
  5. Не використовуйте STL в режимі налагодження. (і ви завжди хочете, щоб режим налагодження працював)

2

Позначення Big-O - це за визначенням асимптотична складність, тобто воно показує, як масштаб часу, коли N (або будь-які змінні у вас є) стає "дуже" великим. Щоб повторно повторити коментар Тетрада (який я збільшив) "дані є королем". Якщо N "дуже великий" у вашій конкретній ситуації, це має значення, якщо N "дуже малий", це не має значення. Досвід та практика дадуть вам уявити, як оцінити "дуже велике" та "дуже мало".

Очевидно, завжди спочатку профілюйте та оптимізуйте останні (якщо ви не робите дослідження техніко-економічного обґрунтування)


1

Важливість Big-O у вашому програмному забезпеченні - O (N 2 ). Зі зростанням N важливість правильного алгоритму зростає ще більше. :)


Чи це не залежить від того, як часто цей алгоритм викликається ..?
bobobobo

Певною мірою. Але якщо на це потрібно три дні, це, мабуть, не має значення, якщо ви зателефонуєте лише один раз. :)
Kylotan

1

Big-O - це лише настанова - те, що говорить вам про грубую ефективність, яку ви можете очікувати від алгоритму, - і як ви повинні розраховувати на масштабність продуктивності, збільшуючи розмір набору даних . Ви повинні пам’ятати дві основні речі щодо Big-O:

1) Якщо у вас є два алгоритми, які в основному роблять те саме, але в одному є кращий O, ви, ймовірно, повинні піти на цей (очевидно)

2) Big O стосується асимптотичного аналізу . Big-O дійсно вступає в гру лише тоді, коли n є великим . Наприклад, алгоритм O (n) може бути дуже схожим по продуктивності з O (n ^ 2). .. для малих n . Якщо ви говорите про алгоритм, який вимагає n ^ 2 операцій на вершину, але n = 2 або n = 3, то між алгоритмом O (n ^ 2) немає великої різниці (приймаючи 4 та 9 ops відповідно) і a O (n) один (2 і 3 ops відповідно). Однак якщо n = 9, то ви раптом говорите про 81 операцію для алгоритму O (n ^ 2) і лише 9 для O (n) однієї - більша різниця - а якщо n = 100, то ви якщо говорити про 100 ops проти 10000 - набагато більша різниця.

Таким чином, ви завжди повинні розглядати Big-O в такому світлі: мається на увазі порівняння алгоритмів, які роблять те саме, що базується на найгіршій якості продуктивності, коли n стає великим . Різниці між алгоритмами можуть бути майже незначними, коли n дуже мало.


0

Я не маю жодних посилань, але Big O принаймні зручно бути в курсі при аналізі проблеми та обговоренні. З іншого боку, звичайно, якщо версія O (log n) має більше задіяний O, ніж версія O (n), це порівняння. І як у всьому, тут завжди є розпродаж. Космічна складність може бути проблемою, хоча це може виражатися і в O загалом. Звичайний аналіз випадків ... тим більше, тому що ви також не хочете, щоб люди, які пережили свою людину, шипкували. Простота щодо складності, на мою думку, в розробці ігор відносно марна, оскільки швидкість майже завжди є проблемою, тому, якщо простота не призводить до прискорень (але це означає, що ваш складний випадок був неправильним з неправильних причин) простота повинна буде йти через вікно на користь швидкості. Але Big O, безумовно, корисний,


0

Коли прототип функції гри або аспект гри, ви не повинні турбуватися про оптимізацію взагалі .

У процесі прототипування та дізнання про особливості цієї функціональності необхідні оптимізації стануть очевидними та стануть чинником остаточного дизайну на зразок 2-ї природи ... більшість часу.

Не потій.


"Коли ви прототипуєте ігрову функцію чи аспект гри, ви не повинні турбуватися про її оптимізацію взагалі." Це вірно іноді, але не завжди. Деякі ігри, такі як Dead Rising, покладаються на швидке виконання, щоб зробити основний ігровий механік - сотні зомбі в реальному часі - можливим.

Який відсоток розвитку ігор складає прототипування? Зрештою ви хочете щось доставити , правда?
dash-tom-bang

0

Це не повинно бути всім і кінцевим. Але це допомагає розібратися з очевидними проблемами, які можуть спричинити хіти до ефективності; навіщо використовувати щось в O (n ^ 2) час, коли ви можете зробити те ж саме в O (log n) час?

Я думаю, що це стосується ігор більше, ніж більшість інших галузей, оскільки ринок - це той, хто найбільше помітить проблеми зі швидкістю. Комусь, хто використовує текстовий процесор, буде байдуже, чи є затримка на півсекунди для виконання дії X, але геймери, ймовірно, перейдуть «omg omg гра Y так повільно, що потрібно робити віки Z».


0

В ігровій (і більшості інших) розробках ми випираємо приблизно одну додаткову операцію, виконану за цикл:

for (int i = 0; i < array.length; i ++) { /* ... */ }

vs.

for (int i = 0, l = array.length; i < l; i ++) { /* ... */ }

У більшості сучасних ігор є фізика, і ви знайдете проблему моделювання n-body . У наївному алгоритмі це O (n ^ 2), але є оптимізація, яка робить його O (n log n) (але приносить у жертву певну точність).

Можна сказати, що ви не програмуєте взаємодію гравітації та частинок, а як щодо поведінки команди армії (зомбі), де вони рухаються залежно від інших місць (більш конкретним словом: рой)?

У звичайному алгоритмі виявлення зіткнень часова складність становить O (n ^ 2), як і n-тіло. Однак є кращий спосіб: розділіть світ на багато маленьких частин, щоб зіткнення виявляли лише об'єкти всередині однієї частини. Дивіться http://www.videotutorialsrock.com/opengl_tutorial/collision_detection/text.php .

Якщо ви граєте за допомогою сценарію, НЕ змушуйте скриптера писати в сценарій алгоритми розбиття чисел O (n ^ 2) (і вище), наприклад пошук у мішку користувача. Зробіть натомість вбудовану функцію в код.


1
Обидва приклади вашого коду є O (n). Обговорення Big-O не мають нічого спільного з "однією додатковою операцією на цикл", а, скоріше, з "одним додатковим пошуком через усе за ітерацію циклу над усім".
dash-tom-bang

-2

У реальному світі враховуються лише сирі показники. Тепер, Big-O алгоритму може слугувати першою вказівкою, що використовувати, але залежно від апаратних засобів реалізація може бути надзвичайно неефективною. Наприклад, лінійний пошук часто може бути швидшим, ніж двійковий пошук, тому що ви отримуєте лінійний доступ до пам'яті і немає гілок.

Крім того, через поточний напрямок у багатопотокових платформах та архітектурах Big-O втрачає велике значення, оскільки враховує лише вертикальну масштабованість пам'яті або торкається даних за операцію, а не враховує, як алгоритм луски з більшою кількістю ниток.


3
Це неправильно, позначення Big O використовується для показу верхніх меж паралельних алгоритмів так само, як лінійних алгоритмів. Big O можна використовувати для паралельних архівів читання / одночасного запису тощо. Ви навіть можете робити шалені речі, як сортування в O (1) з n ^ 2 процесорами, так
Девід Янг,

Девіде, у тебе є приклади з реального життя? Я маю на увазі, я можу також збільшити кількість яблук, яку може носити група людей, але це не означає, що воно вживається чи є корисним. З мого досвіду, більшість часу гамедев вибирає свої (паралельні) алгоритми на основі вихідної продуктивності, а не на своїх функціях зростання.
Джаспер Беккерс

3
"сортування в O (1) з n ^ 2 процесорами" Я, як правило, вважаю, що це використання O вводить в оману, оскільки використання ресурсів все ще O (n ^ 2), незалежно від способу вирішення проблеми. Більша кількість потоків не означає лише більшу кількість циклів процесора в секунду.
Річард Фабіян

Сортування в O (1) з n ^ 2 процесорами - не найкращий приклад, такий тип позначень Big-O, мабуть, найчастіше спостерігається в наукових колах. Щось подібне до цього cs.bu.edu/~best/crs/cs551/homeworks/hw1/pram.html Більш реалістичні паралельні алгоритми можуть використовувати процесори журналу (n). Цей тип матеріалів краще підходить для перевантаження на обробку GPU або супер обчислення, де є сотні ядер.
Девід Янг

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