У чому полягають супроводи c ++ 20?
Чим він відрізняється від «Паралелізму2» або / та «Конкурсу2» (дивіться нижче на зображення)?
Зображення нижче від ISOCPP.
У чому полягають супроводи c ++ 20?
Чим він відрізняється від «Паралелізму2» або / та «Конкурсу2» (дивіться нижче на зображення)?
Зображення нижче від ISOCPP.
Відповіді:
На абстрактному рівні Coroutines розділив ідею відключення стану виконання від ідеї наявності потоку виконання.
SIMD (одноразова множина даних інструкцій) має кілька "потоків виконання", але лише один стан виконання (він просто працює на декількох даних). Можливо, паралельні алгоритми трохи подібні до того, що у вас є одна "програма", що працює на різних даних.
Нитка має кілька "потоків виконання" та кілька станів виконання. У вас є більше однієї програми та більше ніж один потік виконання.
Супроводи мають кілька станів виконання, але не володіють потоком виконання. У вас є програма, і програма має стан, але вона не має нитки виконання.
Найпростіший приклад співпраць - це генератори чи перелічувачі з інших мов.
У псевдокоді:
function Generator() {
for (i = 0 to 100)
produce i
}
Generator
Називається, і перший раз , коли він назвав її повертає 0
. Його стан запам'ятовується (наскільки стан залежить від впровадження процедур), і наступного разу, коли ви його зателефонуєте, він продовжується там, де він припинився. Таким чином, він повертається 1 наступного разу. Потім 2.
Нарешті вона доходить до кінця циклу і відпадає від кінця функції; поправка закінчена. (Те, що відбувається тут, залежить від мови, про яку ми говоримо; у python - це виняток).
Супротивники приводять цю здатність до C ++.
Існує два види корутин; складний і нестабільний.
Безпроблемна супровідна програма зберігає лише локальні змінні у своєму стані та місці виконання.
Складний інструмент зберігає цілий стек (як нитка).
Безрецептурні супроводи можуть мати надзвичайно малу вагу. Остання пропозиція, яку я прочитав, стосувалася, в основному, переписування вашої функції в щось схоже на лямбда; всі локальні змінні переходять у стан об'єкта, а мітки використовуються для переходу до / з місця, де підпрограма «виробляє» проміжні результати.
Процес отримання вартості називається "урожайність", оскільки супроводи трохи схожі на кооперативну багатопоточність; ви повертаєте точку виконання назад абоненту.
Boost має реалізацію складних процедур; це дозволяє викликати функцію, щоб приносити вам. Складні супроводи є більш потужними, але й дорожчими.
Співпраці більше, ніж простий генератор. Ви можете чекати на програмі в супровідній програмі, що дозволяє вам складати корисні програми корисним чином.
Супроводи, як-от if, циклі і функціонування дзвінків, - це ще один вид "структурованого goto", який дозволяє висловлювати певні корисні зразки (наприклад, державні машини) більш природним чином.
Конкретна реалізація Coroutines в C ++ є дещо цікавою.
На самому базовому рівні він додає декілька ключових слів до C ++: co_return
co_await
co_yield
разом із деякими типами бібліотек, які працюють з ними.
Функція стає супровідною програмою, маючи в своєму тілі одне з тих. Тож у своїй декларації вони не відрізняються від функцій.
Коли одне з цих трьох ключових слів використовується у функціональному тілі, відбувається деяке стандартне доручення вивчення типу повернення та аргументів, і функція перетворюється в супровід. Це вивчення повідомляє компілятору, де зберігати стан функції, коли функція призупинена.
Найпростіша програма - це генератор:
generator<int> get_integers( int start=0, int step=1 ) {
for (int current=start; true; current+= step)
co_yield current;
}
co_yield
призупиняє виконання функцій, зберігає стан у generator<int>
, а потім повертає значення current
через generator<int>
.
Ви можете перевести цикл на повернені цілі числа.
co_await
тим часом дозволяє скласти одну кореневу програму на іншу. Якщо ви перебуваєте в одній програмі, і вам потрібні результати очікуваної речі (найчастіше корупції), перш ніж прогресувати, ви co_await
її виконаєте . Якщо вони готові, ви продовжуєте негайно; якщо ні, ви призупиняєте, поки не буде готове очікування, яке вас чекає.
std::future<std::expected<std::string>> load_data( std::string resource )
{
auto handle = co_await open_resouce(resource);
while( auto line = co_await read_line(handle)) {
if (std::optional<std::string> r = parse_data_from_line( line ))
co_return *r;
}
co_return std::unexpected( resource_lacks_data(resource) );
}
load_data
- це посібник, який генерує, std::future
коли відкритий названий ресурс, і нам вдається проаналізувати точку, де ми знайшли запитувані дані.
open_resource
і read_line
s - це, ймовірно, асинхронні підпрограми, які відкривають файл і читають з нього рядки. co_await
Поєднує Призупинення та стан готовності load_data
до їх прогресу.
Спроби C ++ набагато гнучкіші, ніж це, оскільки вони були реалізовані як мінімальний набір мовних функцій на вершині типів простору користувача. Типи простору користувача ефективно визначають, що co_return
co_await
і що co_yield
означає - я бачив, як люди використовують його для реалізації монадичних необов'язкових виразів, щоб a co_await
на порожній необов'язково автоматично пропонував порожній стан зовнішній необов'язковий:
modified_optional<int> add( modified_optional<int> a, modified_optional<int> b ) {
return (co_await a) + (co_await b);
}
замість
std::optional<int> add( std::optional<int> a, std::optional<int> b ) {
if (!a) return std::nullopt;
if (!b) return std::nullopt;
return *a + *b;
}
;;
.
Співпраця - це як функція C, яка має кілька операторів повернення, і коли вона викликається 2-й раз, не запускає виконання на початку функції, а в першій інструкції після попереднього виконаного повернення. Це місце збереження зберігається разом із усіма автоматичними змінними, які б існували на стеку в функціях, що не містять корекції.
У попередній експериментальній реалізації програми Microsoft використовували скопійовані стеки, щоб ви могли навіть повернутися з глибоко вкладених функцій. Але цю версію комітет C ++ відхилив. Ви можете отримати цю реалізацію, наприклад, з бібліотеки волокон Boosts.
припущення повинні бути функціями (в C ++), які здатні "чекати" завершення якоїсь іншої програми і надавати все необхідне для припинення, призупинення, очікування, розпорядку. Особливістю, яка є найбільш цікавою для людей із С ++, є те, що спрощення в ідеалі не займатимуть місця у стеці ... C # вже може зробити щось подібне з очікуванням та поступкою, але C ++, можливо, доведеться перебудувати для його введення.
паралельність сильно орієнтована на розмежування проблем, коли стурбованість є завданням, яке передбачається виконати програмою. це розділення проблем може бути здійснене кількома способами ... як правило, делегуванням. ідея одночасності полягає в тому, що низка процесів може протікати незалежно (розділення проблем), і «слухач» спрямовуватиме все, що виробляється тими окремими проблемами, куди не слід. це сильно залежить від якогось асинхронного управління. Існує ряд підходів до паралельності, включаючи програмування, орієнтоване на аспекти та інші. У C # є оператор «делегат», який працює досить непогано.
паралелізм звучить як паралельність і може бути задіяний, але насправді це фізична конструкція, що включає багато процесорів, розташованих більш-менш паралельно, з програмним забезпеченням, яке здатне направляти частини коду до різних процесорів, де він буде запущений, і результати будуть отримані назад синхронно.