Посібник об'єднання проти ниток


13

Яка різниця між співпрограмою та ниткою? Чи є якісь переваги використання одного над іншим?


3
Розмови про роботу над основною ниткою.
Woltus


2
Ви не можете використовувати будь-які функції Unity в потоці. Супроводи можуть.
Гелій


1
@Hellium Correction, ви не можете використовувати жодні функції Unity в іншому потоці, тобто функції Unity можна використовувати в основному потоці .
Фарап

Відповіді:


24

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

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

З іншого боку, з потоками ви абсолютно не знаєте, в якому стані знаходиться основний цикл Unity (він може насправді більше не працювати). Тож ваша нитка може спричинити досить багато хаосу, роблячи щось за той час, коли цього робити не повинно. Не торкайтеся будь-яких нативних функцій Unity з підрядного потоку . Якщо вам потрібно зв’язатись між підпотоком та вашим основним потоком, попросіть цей потік записати в якийсь безпечний для потоків (!) Контейнер-об'єкт, а MonoBehaviour прочитає цю інформацію під час звичайних функцій подій Unity.

Недоліком того, що не робити «справжню» багатопотоковість, є те, що ви не можете використовувати супроводи для паралелізації обчислювальних процесором обчислень над декількома ядрами процесора. Однак ви можете використовувати їх, щоб розділити обчислення на кілька оновлень. Тож замість того, щоб заморожувати гру на одну секунду, ви отримуєте лише нижчий середній кадр протягом декількох секунд. Але в такому випадку ви відповідаєте за yieldсвою програму, коли ви хочете дозволити Unity запустити оновлення.

Висновок:

  • Якщо ви хочете використовувати асинхронне виконання для вираження логіки гри, використовуйте підпрограми.
  • Якщо ви хочете використовувати асинхронне виконання для використання декількох ядер CPU, використовуйте потоки.

Коментарі не для розширеного обговорення; ця розмова була переміщена до чату .
MichaelHouse

10

Розслідування - це те, що ми в Computer Science називаємо "кооперативним багатозадачністю". Вони є способом для безлічі різних потоків виконання, щоб спільно взаємодіяти з іншими. При спільній багатозадачності один потік виконання має єдине безперечне право власності на процесор, поки він не досягне а yield. У цей момент Unity (або будь-яка інша рамка, яку ви використовуєте), має можливість переключитися на інший потік виконання. Потім він також отримує єдине безперечне право власності на процесор, поки він не з'явиться yield.

Нитки - це те, що ми називаємо «попереджувальною багатозадачністю». Коли ви використовуєте потоки, фреймворк залишає за собою право в будь-який момент зупинити порядок потоку середньої думки та перейти на інший потік. Не має значення, де ти. Вас навіть можна зупинити частково, записавши змінну в пам'ять в деяких випадках!

У кожного є плюси і мінуси. Мінуси супротивів, мабуть, найлегше зрозуміти. По-перше, всі процедури виконуються на одному ядрі. Якщо у вас є чотирьохядерний процесор, для підручних програм буде використовуватися лише одне з чотирьох ядер. Це спрощує речі, але в деяких випадках може бути проблемою ефективності. Другий результат полягає в тому, що ви повинні знати, що будь-яка програма може зупинити всю вашу програму, просто відмовившись від цього yield. Це було проблемою на Mac OS9, багато років тому. ОС9 підтримує лише багатозадачність спільної роботи на всьому комп’ютері. Якщо одна з ваших програм зависла, це може зупинити комп'ютер настільки люто, що ОС не змогла навіть надати текст повідомлення про помилку, щоб повідомити, що сталося!

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

Нитки - це зовсім інший звір. Ви завжди повинні бути на сторожі від можливості того, що інша нитка може перервати вас у будь-який часі возитися зі своїми даними. Бібліотеки ниток надають цілий набір потужних інструментів, які допоможуть вам у цьому, такі як мутекси та змінні умови, які допомагають вам повідомити ОС, коли це безпечно для запуску однієї з ваших інших потоків і коли вона небезпечна. Існують цілі курси, присвячені тому, як добре використовувати ці інструменти. Одне з відомих питань, яке виникає, - це "глухий кут", який полягає в тому, що обидві нитки "застрягають", чекаючи, коли інша звільнить деякі ресурси. Ще одне питання, що дуже важливо для Unity, полягає в тому, що багато бібліотек (як Unity) не розроблені для підтримки дзвінків з декількох потоків. Ви можете дуже легко зламати рамки, якщо не звернете увагу на те, які дзвінки дозволені, а які заборонені.

Причина такої додаткової складності насправді дуже проста. Переважна багатозадачна модель дійсно схожа на багатопотокову модель, яка дозволяє вам не тільки перебивати інші потоки, але і фактично запускати нитки поруч на різних ядрах. Це надзвичайно потужно, оскільки це єдиний спосіб реально використовувати ці нові чотирьохядерні та шістнадцяткові коди CPU, які виходять, але відкривають вікно pandoras. Правила синхронізації щодо управління цими даними у багатопотоковому світі є позитивно жорстокими. У світі C ++ є цілі статті, присвячені MEMORY_ORDER_CONSUMEяким - один куточок багатопотокової синхронізації itty-bitty-teeny-weenie.

Отже, мінуси різьблення? Просто: вони важкі. Ви можете зустріти цілі класи помилок, яких ви ніколи не бачили. Багато хто з так званих "heisenbugs", які іноді з'являються, а потім зникають, коли ви їх налагоджуєте. Інструменти, які вам дають вирішити, дуже потужні, але вони також дуже низькі. Вони розроблені таким чином, щоб бути ефективними в архітектурі сучасних мікросхем, а не розроблені для зручності використання.

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

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


Нитки додають складності переважно у випадках, коли операції та залежності переплітаються. Якщо основний цикл гри містить три функції: x (), y () і z (), і жодна з них не впливає на все, що потрібно іншому, запускаючи всі три з них одночасно, але потім чекаючи, коли все завершиться, перш ніж продовжити дозволяють отримувати певну вигоду від багатоядерної машини, не потребуючи додаткової складності. Хоча змінні умови зазвичай використовуються в поєднанні з мютексами, парадигма незалежних паралельних кроків насправді не потребує мутексів як таких ...
supercat

... але просто спосіб, щоб потоки, які обробляють y () і z (), чекали, поки вони спрацьовують, а потім спосіб для основного потоку чекати, після запуску x (), до y () і z () завершили.
supercat

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

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

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

2

У найпростіших умовах ...


Нитки

Потік не визначає, коли він поступатиметься, операційна система ("ОС", наприклад Windows) вирішує, коли потік виведений. Операційна система майже повністю відповідає за планування потоків, вона вирішує, які потоки запускати, коли їх запускати і на скільки часу.

Крім того, потік може запускатися синхронно (один потік за іншим) або асинхронно (різні потоки, що працюють на різних ядрах ЦП). Здатність запускати асинхронно означає, що потоки можуть зробити більше роботи за один і той же час (тому що нитки буквально роблять дві речі одночасно). Навіть синхронні потоки отримують багато роботи, якщо ОС гарно планує їх.

Однак ця додаткова потужність переробки має побічні ефекти. Наприклад, якщо два потоки намагаються отримати доступ до одного і того ж ресурсу (наприклад, до списку) і кожен потік може бути випадковим чином зупинений у будь-якій точці коду, модифікації другого потоку можуть заважати модифікаціям, зробленим першим потоком. (Див. Також: Умови гонки та тупик .)

Нитки також вважаються «важкими», оскільки вони мають великі накладні витрати, що означає, що за перемикання ниток виникає значна часова кара.


Розслідування

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

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

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


Підсумок:

Нитка:

  • Синхронний або асинхронний
  • Поступається ОС
  • Вийшов випадковим чином
  • Важка

Параметр:

  • Синхронний
  • Врожайність
  • Врожайність за вибором
  • Легкий

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

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