|
|
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
Добрый день коллеги. С пятницей. Я долго думал куда поместить этот сабж. В С++, Java или программинг. И решил все таки здесь т.к. тема достаточно общая и о ней стоит говорить сразу в контексте многих языков. Тема - со-программами или co-routines Я квотирую определение с вики чтоб было понятно wikiСопрограмма (англ. coroutine) — компонент программы, обобщающий понятие подпрограммы, который дополнительно поддерживает множество входных точек (а не одну как подпрограмма), остановку и продолжение выполнения с сохранением определённого положения. Сопрограммы являются более гибкими и обобщёнными, чем подпрограммы, но реже используются на практике. Применение сопрограмм являлось методикой ещё ассемблера, практиковалось лишь в некоторых высокоуровневых языках (Simula, Modula-2). Сопрограммы хорошо пригодны для реализации многих похожих компонентов программ (итераторов, бесконечных списков, каналов, совместных задач). Под катом - мотивация сабжа для меня. Год назад я пытался нарисовать картинку Тяпничная география - распределение Ipv4 адресов по странам и отображение этого на диаграмме в виде цветных квадратов. Это была не бизнес разработка и чуть позже она мне надоела и я ее отложил. Для рисования квадратов я кодил заполняющую кривую Гилберта. И резальтатом разработок была экспериментальная консольная тулза https://sourceforge.net/p/countryipdiagram/code/HEAD/tree/trunk/utils/src/gilbertroute.c которая должна быть генератором координат Гилберта. Сами коды выводились в stdout для передачи в другую утилиту. Но работать с pipeline-ом процессов неудобно. Мне нужна была генерализация алгоритма в виде шаблона алгорима чтоб я мог его подставлять в любой код. В чем была сложность? В рекурсивности самого алгоритма. Как вы знаете, писать рекурсивный итератор - довольно неудобно. Нужно либо создать конечный автомат со стеком и работать с ним. (Это нетривиально и чревато ошибками). Кроме того большинство стандартных алгоритмов доступных в сорцах уже изначально написаны под рекурсию и их удобно заимствовать в том виде как есть без всяких приседаний и переписываний. Второй вариант - использовать механизмы очередей (на базе BlockingQueue в Java к примеру) для того чтобы иммитировать поведение итератора с рекурсией. Способ оригинальный. Но есть недостаток. Мы вводим еще один вычислительный поток в задачу которая по сути является однопоточной. Отсюда автоматом - структуры данных которым нужна синхронизация (BlockingQueue) и накладные. Вобщем нужен гладкий и удобный механизм разворачивания рекурсивных функций в генераторы. Вобщем как обстоят дела с со-программами (co-routines) в С/С++/C#/Java/Groovy/Scala/JavaScript/Delphi. Прошу прощения если я не упомянул ваш любимый язык X. Я просто не успел просмотреть обзоры фичей всех ваших языков. Я вот сделал некоторую табличку в которой попробовал обрисовать положение вещей на текущий момент Поддержка со-программ в ЯП LanguageCo-routines supportCno supportС++Возможно с поддержкой boost::coroutinesC#with yield returnJavano suportGroovy?Scalawith yieldDelphino supportJava Script Since ECMA6 В многочисленных статьях также упоминается что для поддежки co-routines язык или среда должен поддерживать continuations. Вот такая ситуация. У кого какие были практики с coroutines? Поделитесь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 15:17 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
Было бы круто, если бы был полностью рабочий локализованный пример, который использует сопрограммы или который не использует, но при их наличии был бы намного понятнее/быстрее, на любом из упомянутых языков на онлайн компиляторе: http://ideone.com/ Так было бы намного наглядней. Пока что ни разу не встречал такого примера. Либо примеры все усложняют, либо упрощают, но используют какие-то гипотетические сторонние функции, которые почему-то не могут сохранить свое текущее состояние: ни в передаваемую структуру, ни в объект членом которого они являются, ни в стороннюю структуру куда можно обратиться по хэндлеру. Нафига выходить по yield, выходи по return, а текущее состояние всех итераторов храни как члены класса, сохранятся в объекте. Если просто хочется распараллеливания, то используй потоки, выходи по yield(), и используй потокобезопасный обмен - ровно теже сопрограммы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 16:46 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonУ кого какие были практики с coroutines? Поделитесь. Используем в продакшене Boost.Coroutine (для асинхронных операций). Код на порядок проще и понятнее, чем с колбэками. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:01 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
mayton, а goto отменили что ли уже? как то давно, когда студентом был, делал нитевую многопоточность на TurboPascal-е, в общем-то такую вещь там можно было реализовать. каналы как абстракция делаются в любом из языков поддерживающих генерики или метапрограммирование, зачем для этого делать языковые конструкции? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:04 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
Вася УткинНафига выходить по yield, выходи по return, а текущее состояние всех итераторов храни как члены класса, сохранятся в объекте. Так написал же человек - не хочет он явно хранить состояние, когда алгоритмически никакого состояния нет. Т.е. то что вы предлагаете, это усложнение алгоритма. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:04 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
Я щас сходу не готов дать охватывающий пример. У меня щас нет такого под рукой. Но я могу привести контр-пример. Возьмите любую древовидную структуру данных. Или графовую. И сделайте по ней алгоритм итератора. Обеспечте интерфейс который обходит все узлы: Код: plaintext 1. 2. 3. 4. Это и есть контр пример. Тоесть пример того как кодить неудобно. Без использования уступчивого return, мультипоточности и contnuations. Это моё ИМХО. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:04 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)mayton, а goto отменили что ли уже? как то давно, когда студентом был, делал нитевую многопоточность на TurboPascal-е, в общем-то такую вещь там можно было реализовать. каналы как абстракция делаются в любом из языков поддерживающих генерики или метапрограммирование, зачем для этого делать языковые конструкции? Ну... я готов покорректировать табличку. Наверное в Турбо-Паскале есть языковый API для работы с каналами. Я этого не знал. Приведите пример плиз. Буду признателен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:12 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonНу... я готов покорректировать табличку. Наверное в Турбо-Паскале есть языковый API для работы с каналами. Я этого не знал. языковых конструкций нету, я же говорю делал нитевидную многозадачность под досом выделялась память под стэк и проца yield, которая меняла регистр SP на доступные стэки. Сомневаюсь что так можно под виндой сделать, хотя попробовать не мешает ... а каналы генериками в Delphi, fpc делаются довольно легко ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:45 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)а каналы генериками в Delphi, fpc делаются довольно легко Но это language features? Или нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:48 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonЯ щас сходу не готов дать охватывающий пример. У меня щас нет такого под рукой. Но я могу привести контр-пример. Возьмите любую древовидную структуру данных. Или графовую. И сделайте по ней алгоритм итератора. Обеспечте интерфейс который обходит все узлы: Код: plaintext 1. 2. 3. 4. Это и есть контр пример. Тоесть пример того как кодить неудобно. Без использования уступчивого return, мультипоточности и contnuations. Это моё ИМХО. а в чем проблема указатели в стэке сохранить? Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:51 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonkealon(Ruslan)а каналы генериками в Delphi, fpc делаются довольно легко Но это language features? Или нет? это скорее language-oldest, зачем это делать если либами можно сделать? да и с ОС проблемы, она просто так стэковые регистры менять не даёт ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 17:55 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan) Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Эээ... надо подумать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 18:09 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
yield в C# это тема, правда я в нее еще не вникал глубоко. Тут фундаментально меняется подход, ты получаешь на вход интерфейс, который будет (будет в будущем) возвращать тебе последовательность, дальше можно его передать на вход следующей функции и т.д. Это и есть основа LINQ. И в итоге это выглядит так, например найти первое число в массиве между 1-10 Код: c# 1. и тут перебор будет именно до первого удовлетворяющего условию. Синтаксический сахар конечно, но сахар он на то и нужен чтобы сладко было. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 20:14 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
Dima T, это пример вырожденный. Его легко итерациями сделать. А вот задачка обхода деревьев как функция которая возвращает узлы - это красиво. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 20:38 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonDima T, это пример вырожденный. Его легко итерациями сделать. Я не спорю, я же написал что это синтаксический сахар, но я не люблю С/С++ именно за то что обязательно надо это делать, т.е. писать кучу букав, потом отлаживать, а тут написал одну строчку и получил что хотел. Мне не нравится С именно поэтому, т.к. для элементарного действия надо написать портянку на два экрана, когда в высокоуровневом ЯП это одна строка. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 20:52 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
Дима. 1) Я понял. Я думаю что ближайшие лет 10 основной темой споров будут доводы за и против лямбд и Stram-операций в обычных ЯП. У меня отношения к лямбдам весьма сдержанное. Тоесть я сперва хочу понять pitfalls в части их практического использования (Java) как то отладка, области видимости (лямбда не видит не статичные переменные класса), и обработка исключений внутри лямбд (куда мы вываливаемся?) и конечно-же перформанс. Но эта тема другого топика. 2) Я вернусь к своим баранам. А именно к coroutine. Разворачивая рекурсию в С-программе которую я привел выше я пришел к следующему итератору. В нем полезным по сути является копи-паста С-программы а именно рекурсивная процедура обхода квадрата по Гилберту. Остальное - шлак. Все эти обвязки, потоки и Блокирующая очередь - просто служебные тулзы которые я притянул за уши только чтобы достать координаты пикселов. Есть также странные хардкоденные константы типа Position.Dummy смысл которых - уведомить итератор о том что очередь завершена и больше данных ждать не стоит. Вобщем много всякой фигни. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. Меня это обескураживает и я ищу простые лаконичные механизмы не жрущие списки памяти и в то-же время выдающие сиквенс значений из рекурсии. Напомню о проблеме. Мне надо было заполнить пикселами картинку в порядке кривой Гилберта. Но я не хотел хардкорное решение. Мне нужны были компоненты которые "чертят" спирали, Z-кривые, змейки и кривые Гилберта и Пеано. И пока у меня не было такой компоненты сам кодинг плаката с IP-диаграммой мне был не интересен. И мне нужен был механизм переключений между этими "чертилками". 3) По поводу Streams (Java8). Я надеюсь они мне позволят заменить со-программы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 21:17 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonМеня это обескураживает и я ищу простые лаконичные механизмы не жрущие списки памяти и в то-же время выдающие сиквенс значений из рекурсии. рекурсия это и есть список памяти, ты просто фактически не хочешь о нём заботиться сам Рекурсия кстати процентов на 20-30 медленнее (за счёт сохранения всех данных). Чем стэковый автомат в уже выделенном блоке. За простоту кода приходится платить ресурсами. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 23:08 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)рекурсия это и есть список памяти, ты просто фактически не хочешь о нём заботиться сам Рекурсия кстати процентов на 20-30 медленнее (за счёт сохранения всех данных). Чем стэковый автомат в уже выделенном блоке. За простоту кода приходится платить ресурсами. Очень часто мы (разработчики) согласны платить 20-30% (здесь я сомневаюсь надо пересчитать) но при этом иметь простой концептуальный код. Если yield return несет в себе нулевые накладные расходы (синхронизации нет, нет потоков, IPC, и очередей) то я согласен и я хочу использовать этот return в противоположность разворачиванию рекусии в конечный автомат. Заметьте что мы с вами еще не рассматривали оценку сложности этого процесса. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 23:20 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
Я имею в виду оценку сложности процесса переписывания рекурсии в автомат со стеком. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 23:22 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonЕсли yield return несет в себе нулевые накладные расходы (синхронизации нет, нет потоков, IPC, и очередей) то я согласен и я хочу использовать этот return в противоположность разворачиванию рекусии в конечный автомат. несёт, для них нужен отдельный блок стэка, сколько его выделить 100кб, 1Мб или больше? траты на yield в общем случае : все регистры, связка pushad-popad довольно быстрая, но не бесплатная операция. это мы ещё не вспоминаем про регистры fpu maytonЗаметтье что мы с вами еще не рассматривали оценку сложности этого процесса. есть ещё вариант: если в функциональном стиле написать алгоритм, то его можно довольно просто механически разложить через комбинаторы в "автомат со стэковой памятью" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.08.2016, 23:39 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan), спасибо. Но я не специалист в FreePascal. Вряд-ли я могу собрать это. А вот по поводу комбинаторов и автоматов со стеком - подкинь материала. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.08.2016, 15:09 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
maytonkealon(Ruslan), спасибо. Но я не специалист в FreePascal. Вряд-ли я могу собрать это. А вот по поводу комбинаторов и автоматов со стеком - подкинь материала. тут надо подумать, знаю что можно, но вот где и когда читал - подзабыл ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.08.2016, 15:32 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
авторподдерживает множество входных точек (а не одну как подпрограмма), остановку и продолжение выполнения с сохранением определённого положения. ... Применение сопрограмм .....практиковалось лишь в некоторых высокоуровневых языках (Simula, Modula-2) по моему брехня. точки входа в подпрограмму были чуть ли не везде (пл-1 и алгол), а продолжать выполнение с сохранением определенного положения -- можно благодаря static ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2016, 08:14 |
|
||
|
Тяпничная со-программа
|
|||
|---|---|---|---|
|
#18+
tchingizточки входа в подпрограмму были чуть ли не везде (пл-1 и алгол), а продолжать выполнение с сохранением определенного положения -- можно благодаря static Fullstack CoRoutines на основе одной переменной в общем виде повторить не получится смотри пример с обходом бинарного дерева рекурсию всё равно с помощью стэка придётся делать в том или ином виде ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2016, 11:59 |
|
||
|
|

start [/forum/topic.php?fid=16&fpage=27&tid=1340627]: |
0ms |
get settings: |
8ms |
get forum list: |
17ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
33ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
64ms |
get tp. blocked users: |
2ms |
| others: | 227ms |
| total: | 370ms |

| 0 / 0 |
