Что такое сопрограмма? Как они связаны с параллелизмом?
Что такое сопрограмма? Как они связаны с параллелизмом?
Ответы:
Сопрограммы и параллелизм в значительной степени ортогональны. Сопрограммы представляют собой общую структуру управления, посредством которой управление потоком совместно передается между двумя различными процедурами без возврата.
Оператор yield в Python является хорошим примером. Это создает сопрограмму. Когда встречается «yield», текущее состояние функции сохраняется, и управление возвращается вызывающей функции. Вызывающая функция может затем передать выполнение обратно в функцию-получатель, и ее состояние будет восстановлено до точки, где был обнаружен «yield», и выполнение продолжится.
Coroutines are a general control structure whereby flow control is cooperatively passed between two different routines without returning.
<- Это является параллелизм. Слово, которое вы ищете, это параллелизм.
orthogonal = Not similar to each other
?
orthogonal
означает "независимые друг от друга".
Из раздела Программирование на Lua , Coroutines
раздел " ":
Сопрограмма похожа на поток (в смысле многопоточности): это строка выполнения с собственным стеком, локальными переменными и собственным указателем инструкций; но он разделяет глобальные переменные и в основном все остальное с другими сопрограммами. Основное различие между потоками и сопрограммами заключается в том, что концептуально (или буквально в многопроцессорной машине) программа с потоками запускает несколько потоков параллельно. Сопрограммы, с другой стороны, являются совместными: в любой момент времени программа с сопрограммами выполняет только одну из своих сопрограмм, и эта запущенная сопрограмма приостанавливает свое выполнение только тогда, когда она явно запрашивает приостановку.
Итак, суть в том, что сопрограммы являются «совместными». Даже в многоядерной системе в каждый момент времени работает только одна сопрограмма (но несколько потоков могут работать параллельно). Между сопрограммами нет вытеснения, запущенная сопрограмма должна явно отказаться от выполнения.
Для " concurrency
" вы можете сослаться на слайд Роба Пайка :
Параллелизм - это состав самостоятельно выполняемых вычислений.
Таким образом, во время выполнения сопрограммы A она передает управление сопрограмме B. Затем через некоторое время сопрограмма B передает управление обратно сопрограмме A. Поскольку существует зависимость между сопрограммами, и они должны работать в тандеме, поэтому две сопрограммы не являются параллельными .
Я нахожу большинство ответов слишком техническими, хотя это технический вопрос. Мне было трудно понять процесс сопрограммы. Я как бы понимаю, но потом не понимаю.
Я нашел этот ответ очень полезным:
https://dev.to/thibmaek/explain-coroutines-like-im-five-2d9
Цитировать от Идана Арье:
Чтобы развить вашу историю, я бы сказал так:
Вы начинаете смотреть мультфильм, но это вступление. Вместо того чтобы смотреть вступление, вы переключаетесь в игру и заходите в онлайн-лобби - но для этого нужно 3 игрока, и в нем участвуют только вы и ваша сестра. Вместо того, чтобы ждать, пока другой игрок присоединится к вам, переключитесь на домашнюю работу и ответьте на первый вопрос. Второй вопрос имеет ссылку на видео YouTube, которое нужно посмотреть. Вы открываете его - и он начинает загружаться. Вместо того, чтобы ждать загрузки, вы переключаетесь обратно на мультфильм. Вступление окончено, так что вы можете посмотреть. Теперь есть реклама - но тем временем третий игрок присоединился, чтобы вы переключились на игру И так далее ...
Идея состоит в том, что вы не просто переключаете задачи очень быстро, чтобы создать впечатление, что вы делаете все сразу. Вы используете время, которое вы ожидаете, чтобы что-то произошло (IO), чтобы делать другие вещи, которые требуют вашего непосредственного внимания.
Обязательно проверьте ссылку, там гораздо больше, что я не могу все процитировать.
Сопрограмма похожа на подпрограмму / темы. Разница заключается в том, что как только вызывающая сторона вызывает подпрограмму / потоки, она никогда не вернется к функции вызывающей стороны. Но сопрограмма может вернуться к вызывающей стороне после выполнения нескольких фрагментов кода, позволяя вызывающей стороне выполнить часть своего собственного кода и вернуться к точке сопрограммы, где она остановила выполнение и продолжила оттуда. то есть. Сопрограмма имеет более одной точки входа и выхода
В основном, есть два типа сопрограмм:
Kotlin реализует сопрограммы без стеков - это означает, что сопрограммы не имеют собственного стека, поэтому они не отображаются в нативный поток.
Это функции для запуска сопрограммы:
launch{}
async{}
Вы можете узнать больше здесь:
https://www.kotlindevelopment.com/deep-dive-coroutines/
https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9
Из Python Coroutine :
Выполнение сопрограмм Python может быть приостановлено и возобновлено во многих точках (см. Сопрограмму). Внутри тела функции сопрограммы идентификаторы await и async становятся зарезервированными ключевыми словами; выражения await, async for и async with могут использоваться только в телах функций сопрограмм.
Сопрограмма - это функция, которая может приостановить выполнение, чтобы быть возобновленной позже . Сопрограммы без стеков: они приостанавливают выполнение, возвращаясь к вызывающей стороне. Это учитывает последовательный код, который выполняется асинхронно (например, для обработки неблокирующего ввода-вывода без явных обратных вызовов), а также поддерживает алгоритмы для вычислений с отложенным вычислением бесконечных последовательностей и других целей.
Сравните с ответом другого:
На мой взгляд, возобновленная более поздняя часть - это принципиальное отличие, как у @ Twinkle's.
Хотя многие поля документа все еще находятся в стадии разработки, тем не менее, эта часть похожа на большинство ответов, за исключением @Nan Xiao's
Сопрограммы, с другой стороны, являются совместными: в любой момент времени программа с сопрограммами выполняет только одну из своих сопрограмм, и эта запущенная сопрограмма приостанавливает свое выполнение только тогда, когда она явно запрашивает приостановку.
Поскольку он цитируется в программе на Lua, возможно, он связан с языком (в настоящее время не знаком с Lua), не во всех документах упоминается только одна часть.
Отношение с одновременным:
есть часть «Выполнение» сопрограмм (C ++ 20). Слишком долго цитировать здесь.
Помимо деталей, есть несколько состояний.
When a coroutine begins execution
When a coroutine reaches a suspension point
When a coroutine reaches the co_return statement
If the coroutine ends with an uncaught exception
When the coroutine state is destroyed either because it terminated via co_return or uncaught exception, or because it was destroyed via its handle
как комментарий @Adam Arold под ответом @ user217714. Это параллелизм.
Но это отличается от многопоточности.
из std :: thread
Потоки позволяют выполнять несколько функций одновременно. Потоки начинают выполнение сразу после создания соответствующего объекта потока (в ожидании любых задержек планирования ОС), начиная с функции верхнего уровня, предоставленной в качестве аргумента конструктора. Возвращаемое значение функции верхнего уровня игнорируется, и, если оно завершается выдачей исключения, вызывается std :: terminate. Функция верхнего уровня может передавать свое возвращаемое значение или исключение вызывающей стороне через std :: обещание или путем изменения общих переменных (для этого может потребоваться синхронизация, см. Std :: mutex и std :: atomic)
Так как это параллелизм, он работает как многопоточность, особенно когда ожидание неизбежно (с точки зрения ОС), поэтому также сбивает с толку.
Сопрограмма - это особый вид подпрограммы. Вместо того, чтобы отношения «ведущий-ведомый» между вызывающим и вызываемой подпрограммой, существующие с обычными подпрограммами, вызывающий и вызываемые сопрограммы более справедливы.
Сопрограмма - это подпрограмма, которая имеет несколько записей и сама управляет ими - поддерживается непосредственно в Lua
Также называется симметричным управлением: вызывающий и вызываемые сопрограммы находятся на более равной основе.
Вызов сопрограммы называется резюме
Первое возобновление сопрограммы находится в ее начале, но последующие вызовы вводятся в точке сразу после последнего выполненного оператора в сопрограмме.
Сопрограммы неоднократно возобновляют друг друга, возможно, навсегда
Сопрограммы обеспечивают квази-параллельное выполнение программных блоков (сопрограммы); их исполнение чередуется, но не перекрывается
Я нахожу объяснение по этой ссылке довольно простым. Ни один из этих ответов не пытается объяснить параллелизм и параллелизм, кроме последнего пункта в этом ответе .
цитируется из "программирования Erlang" Джо Армстронга, легендарного:
Параллельная программа может работать потенциально быстрее на параллельном компьютере.
Параллельная программа - это программа, написанная на параллельном языке программирования. Мы пишем параллельные программы по причинам производительности, масштабируемости или отказоустойчивости.
Параллельный язык программирования - это язык, который имеет явные языковые конструкции для написания параллельных программ. Эти конструкции являются неотъемлемой частью языка программирования и ведут себя одинаково во всех операционных системах.
параллельный компьютер - это компьютер с несколькими процессорами (процессорами или ядрами), которые могут работать одновременно.
Таким образом, параллелизм - это не то же самое, что параллелизм. Вы все еще можете писать параллельные программы на одноядерном компьютере. Планировщик с разделением времени позволит вам почувствовать, что ваша программа работает одновременно.
Параллельная программа может работать параллельно на параллельном компьютере, но это не гарантируется . ОС может дать вам только одно ядро для запуска вашей программы.
Следовательно, параллелизм - это программная модель параллельной программы, которая не означает, что ваша программа может работать параллельно физически.
Слово «сопрограмма» состоит из двух слов: «со» (кооператив) и «рутина» (функции).
а. это достигает параллелизма или параллелизма?
Проще говоря, давайте обсудим это на одноядерном компьютере.
Параллельность достигается за счет доли времени от ОС. Поток выполняет свой код в назначенные ему временные рамки на ядре ЦП. Это может быть прервано ОС. Это также может дать контроль над ОС.
Сопрограмма, с другой стороны, передает управление другой сопрограмме в потоке, а не ОС. Таким образом, все сопрограммы в потоке все еще используют временные рамки для этого потока, не уступая ядру ЦП другим потокам, управляемым ОС.
Таким образом, вы можете думать, что сопрограмма достигает доли времени пользователем, а не ОС (или квазипараллелизмом). Сопрограммы работают на том же ядре, которое назначено потоку, который запускает эти сопрограммы.
Coroutine достигает параллелизма? Если это код с привязкой к процессору, нет. Как и при распределении времени, вы чувствуете, что они работают параллельно, но их исполнения чередуются, а не перекрываются. Если он связан с вводом-выводом, да, он выполняется параллельно с помощью аппаратного обеспечения (устройства ввода-вывода), а не вашего кода.
б. разница с вызовом функции?
Как показано на рисунке, return
для переключения управления не нужно звонить . Это может дать без return
. Сопрограмма сохраняет и разделяет состояние в текущем фрейме функции (стеке). Так что это намного легче, чем функция, так как вам не нужно сохранять регистры и локальные переменные в стеке и перематывать стек вызовов, когда call ret
.
Я буду расширять ответ @ user21714. Сопрограммы - это независимые пути выполнения, которые не могут выполняться одновременно. Они зависят от контроллера - например, python
библиотеки контроллера - для обработки переключения между этими путями. Но для этого для работы самих сопрограмм нужно вызватьyield
или подобные структуры, которые позволяют приостановить их выполнение.
Вместо этого потоки работают на независимых вычислительных ресурсах и параллельно друг с другом. Так как они находятся на разных ресурсах, нет необходимости вызывать yield, чтобы продолжить выполнение других путей выполнения.
Вы можете увидеть этот эффект, запустив многопоточную программу - например, jvm
приложение - в котором используются все восемь ваших core i7
ядер с гиперпоточностью: вы можете увидеть 797% использования в Activity Monitor
или Top
. Вместо этого при запуске типичной python
программы, даже с coroutines
или, python threading
использование будет максимально на 100%. Т.е. одна машина с гиперпоточностью.