LINUX.ORG.RU

Потоки в Julia: зелёные или нормальные?

 greenshit, , ,


2

5

Собственно, весь вопрос в заголовке: из официальной документации непонятно, являются ли экспериментально реализованные потоки в языке julia настоящими или же это очередная кооперативная фикция, зелёная и в пупырышках. Просто если последнее, то я даже смотреть в сторону этой фигни не стану (в Julia отлично реализовано взаимодействие форкнутых процессов), если же процессы основаны на pthreads или чём-то подобном, то это круто и весьма интересно.

★★★★★

настоящими или же это очередная кооперативная фикция, зелёная и в пупырышках.

Что плохого в green threads?

hateyoufeel ★★★★★
()

блин, а наплодить 100500 потоков и тупо в top посмотреть не? Где дух исследователя, вашу мать?

anonymous
()
Ответ на: комментарий от hateyoufeel

Если N (>1) физических потоков обсуживают M логических, то всё хорошо. Если N всегда равно 1, тогда проблемы со скалируемостью.

anonymous
()
Ответ на: комментарий от anonymous

Ну так это не зелёные потоки виноваты, а отсутствие поддержки SMP.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

Green threads - говно, потому что не используют многоядерную архитектуру процессора в 10-е годы 21-го века.

Ещё вопросы?

DRVTiny ★★★★★
() автор топика
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от DRVTiny

Green threads - говно, потому что не используют многоядерную архитектуру процессора в 10-е годы 21-го века.

Green threads и SMP — довольно ортогональные понятия. Некоторые языки/платформы умеют и то и другое одновременно (Haskell, JVM, Erlang, C++ с Boost Fibers), другие — что-то одно (Python, Ruby).

hateyoufeel ★★★★★
()
Ответ на: комментарий от anonymous

Главная проблема одна - это не параллелизм. Да, всё равно при обращении к памяти или при любом конкурентном IO придётся выстраиваться в цепочку, параллелизм не бывает абсолютным. Но запуск приложения с кучей в действительности последовательно выполняемых «кагбе потоков» - это всегда путь к проблемам «упс, меня застряло» - в форточках это выглядело как курсор-«часики», которые крутились и крутились, и даже не думали «отвисать», а помогал в таких случаях чаще всего Ctrl+Alt+Delete.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Да, всё равно при обращении к памяти или при любом конкурентном IO придётся выстраиваться в цепочку, параллелизм не бывает абсолютным.

Для тебя, наверное, это окажется сюрпризом, но треды ОС от этого тоже страдают.

hateyoufeel ★★★★★
()
Ответ на: комментарий от dave

Потому что им нужны общие данные, поскольку вообще 99% смысла потоков - в том, чтобы легко шарить данные.

Как предполагается шарить данные между этими псевдопотоками, если они работают в рамках разных задач (процессов, если хотите)? Абсолютное большинство современных языков настолько абстрактны и настолько «платформонезависимы», что про shared memory они «не знаю - не слышали», остаются всякие каналы, которые практически везде есть. Но через каналы данные копируются, а не шарятся, вот в чём беда-то ;)

DRVTiny ★★★★★
() автор топика
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Если почитаете внимательно - я о настоящих тредах и говорил: а именно о том, что даже потоки, исполняющиеся на разных ядрах процессора, только при очень грамотно продуманной архитектуре не будут мешаться друг у друга под ногами, постоянно синхронизируясь явным и неявным образом. Но «кооперативные потоки» создают куда более дерьмовую проблему: если один из них наглухо виснет - остальные просто не выполняются. Например, подход python в духе «20 инструкций этого потока, потом 20 - другого» - хорош тольк тогда, когда 20 инструкций одного потока выполняются примерно столько же, сколько и 20 другого, а ещё есть данная Высшими Силами абсолютная гарантия того, что одна из 20-ти инструкций не приведёт к подвисанию потока на пару минуточек.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Но «кооперативные потоки» создают куда более дерьмовую проблему: если один из них наглухо виснет - остальные просто не выполняются.

Это верно только в довольно убогих реализация типа того же питона.

hateyoufeel ★★★★★
()
Ответ на: комментарий от RazrFalcon

Каким образом обычные треды спасают от дедлоков?

Тут разве про дедлок. Как я понимаю зеленый поток это как кооперативная многозадачность, т.е. в зеленом потоке нужно явно вызывать на исполнение другой поток, не? Т.е. некий wait и так должно быть во всех используемых I/O библиотеках иначе никакого конкаренси работать не будет.

Aber ★★★★★
()
Ответ на: комментарий от Aber

в зеленом потоке нужно явно вызывать на исполнение другой поток, не?

Только в C/C++.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

Green threads и SMP — довольно ортогональные понятия. Некоторые языки/платформы умеют и то и другое одновременно ... JVM ...

Помню читал, что java 1.0 умела только green threads, я думал что нативные потоки заменили их совсем. Но green threads как идея в принципе вернулись в виде неблокирующего I/O.

Aber ★★★★★
()

а почему у анонiмуса теперь 5 звезд и пишет он почти по человечески?

qnikst ★★★★★
()
Ответ на: комментарий от DRVTiny

Да, есть вопрос, почему ты выдаешь ложь за правду?

Green threads поддерживают N:M mapping в нормальных языках.

qnikst ★★★★★
()
Ответ на: комментарий от DRVTiny

posix треды не решают ни одну из этих проблем. То, что ты пишешь про форточки абсолютно иррелевантно к green тредам.

Может тебе статей накидать, может хоть полезное что почитаешь?

qnikst ★★★★★
()
Ответ на: комментарий от Aber

Я хз, что ТС подразумевает под «застряло».

Я ноль в гринтредах, но наезжать на них только из-за того, что они не такие как в сишке, как минимум странно.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

Гринтред - это просто очередное «красивое» абстрактное слово. Реализованы везде по-разному, а вся суть сводится к тому же, что делает Coro в Perl (кстати, там это не догадались назвать «зелёными потоками») : N процедур выполняются поочерёдно: немного кода одной процедуры, потом немного когда другой, потом немного третьей. Где-то выполнение прерывается не извне, а прямо в коде процедуры явным образом передаётся управление следующей.

Нужны гринтреды для того, чтобы абстрагироваться от бренного мира, а на самом деле для того, чтобы проще было писать компиляторы и не заморачиваться нативными тредами на разных платформах. Разработчики успешно сами себе находят оправдания - LLVM им нужен, чтобы под разные платформы не писать компиляторы (раньше компилировали в Сишный код, теперь стал модным LLVM), гринтреды - чтобы не заморачиваться с системным программированием под целевые платформы.

А в конечном итоге всё это нужно для того, чтобы больше людей могли создавать больше языков программирования. Огромный профит же от изобилия языков, каждый из которых в равной мере не умеет использовать возможности процессоров. Процессоры уже 10-ть лет развиваются по пути горизонтального масштабирования, наращивая количество ядер каждый год, а языки программирования переизобрели кооперативную многозадачность, которая, казалось бы, протухла ещё в начале 90-х годов.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от qnikst

Чувак, мне жаль, но ты пропустил все лекции по операционным системам и сразу, ничего не читая, принялся писать. Сходи подучись сначала, а потом приходи с новыми полезными знаниями.

И да, прекрати уже писать так, словно ты тупая блондинка в аське, несолидно.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от Aber

Всё верно, только насколько я знаю - «зелёные потоки» как раз наоборот родились из идеи асинхронного (в общем случае - событийного) программирования. Зелёные потоки - вырожденный случай, когда событие - внутреннее и формулируется примерно как «ой, надо бы переключиться на следующий кагбепоток». Триггером события выступают довольно странные вещи типа «эта процедура выполнила свои 20 инструкций - надо переключаться» или «эта процедура выполнила yield, какое счастье, уже таки можно переключаться».

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

В любом случае, даже если эти «кагбе потоки» реализованы где-то лучше, чем в Питоне, в абсолютном большинстве случаев, за исключением разве что Golang'а, их «призвание» - это сделать потоки платформонезависимыми и вообще ни от чего независимыми, а по сути и не потоками вовсе.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

вообще-то поток проработал свою порцию времени и находится в safepoint или поток остановился на получении результата асинхронного IO, ну прям как в OS тредах, только контекст свич отличается на пару порядков.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

интересно, а как из документации на https://docs.julialang.org/en/stable/manual/parallel-computing/ можно не получить ответ на вопрос /0, там черным по белому что количество воркеров задаётся опциями ком строки и фиксировано и как происходит шедулинг.

или тред не для ответа на этот вопрос был, а про лёгкие потоки пообщаться?

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от DRVTiny

в абсолютном большинстве случаев, за исключением разве что Golang'а, их «призвание» - это сделать потоки платформонезависимыми и вообще ни от чего независимыми, а по сути и не потоками вовсе.

Мальчик, ты баклажан. В большинстве случаев green threads сделаны ради упрощения кода, чтобы можно было не писать асинхронную лапшу а-ля node.js или поллинг как в C, а обычных дубовый синхронный код и вместе с тем обрабатывать большое количество событий. В сочетании с развитым IO-менеджером green threads ведут к крайне низким накладным расходам в обмен на сильное упрощение кода. Ты можешь писать такой же код на обычных тредах, но у них накладные расходы на переключение контекста намного выше, поэтому так мало кто делает.

hateyoufeel ★★★★★
()
Ответ на: комментарий от qnikst

Лично я там нашел только упоминание количества ядер процессора, что не говорит ни о чём по сути. Если бы там хоть слово было о том, как именно реализовано, какой либой - я бы не задал этот вопрос.

Насчёт контекст свитчей - когда они делаются в рамках одного процесса, вся эта карусельная внутренняя кухня гринтредов начинает работать только после того как процесс получит свой квант времени. Этот шедуллинг процесса внутри шедуллинга ядра - это какой-то противоесиественный путь самоограничения, слово бы из скромности: не использовать больше квантов времени, стесняться занять дополнительные ядра cpu. Зачем?

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Да вопрос был скорее риторический. Просто хочу сказать, что при правильной реализации зеленые потоки не имеют тех недостатков, что ты им приписываешь (питон к этому списку не относится). Они вполне работают параллельно сразу на нескольких ядрах процессоров. Это уже реальность.

Так скорее проблема, как правильно не вызвать ненароком блокирующий метод. В Haskell она решается, и для этого было сделано очень много. Используются неблокирующие операции IO по возможности.

У зеленых потоков есть, конечно, слабые места, но они немного другие, как я себе представляю

dave ★★★★★
()
Ответ на: комментарий от DRVTiny

Разработчики успешно сами себе находят оправдания - LLVM им нужен, чтобы под разные платформы не писать компиляторы

Удивительно было бы если бы все рвались писать свои кодогенераторы под все платформы.

раньше компилировали в Сишный код, теперь стал модным LLVM

LLVM налагает гораздо меньше ограничений на модель выполнения кода и позволяет писать свои плагины с оптимизациями и прочими ништяками. Как минимум этим он выигрывает у C в качестве бэкенда для компиляции.

гринтреды - чтобы не заморачиваться с системным программированием под целевые платформы.

Особенно если учесть, что из целевых платформ сейчас большинством поддерживаются только pthreads (и то не весь зоопарк реализаций) и венда. Отличная гипотеза! Браво!

hateyoufeel ★★★★★
()
Ответ на: комментарий от dave

Если «зелёные потоки» выполняются на разных ядрах процессоров - значит, они не «зелёные», потому кто кроме ядра ОС назначить потоку выполнения ядро не может никто, а ОС про что-то там «зелёное» ничего близко не знает, для неё это просто процесс, не более того. Другое дело, что сам процесс может создать реальные потоки внутри себя и уже их поделить на «зелёные» - тогда да, эти «кагбепотоки» могут работать на разных ядрах, поскольку нормальные нативные потоки работают на разных ядрах.

Против такой реализации ничего не имею, но языки, которые вообще не осиливают pthreads, и при этом в документации рассказывают что-то про поддержку потоков - меня слегка бесят. Именно по той самой причине, о которой я сказал в самом начале: это не параллелизм, это какая-то имитация бурной деятельности.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

В вопросе есть ложная дихотомия, нормально реализованные грин треды занимают все ядра, у них n рабочих OS процессов, и их количество советуют делать по количеству ядер (как в Джулии). В общем это на 80% даёт ответ, но если читать далее, то в разделе про шедулинг написано, что таски это корутины, и дальше дано пояснение, цитирую: Tasks (aka Coroutines)

Tasks are a control flow feature that allows computations to be suspended and resumed in a flexible manner. This feature is sometimes called by other names, such as symmetric coroutines, lightweight threads, cooperative multitasking, or one-shot continuations

вроде тут однозначно.

я попытаюсь написать более взвешенный и длинный коммент про гринтреды еще

qnikst ★★★★★
()
Ответ на: комментарий от hateyoufeel

Особенно если учесть, что из целевых платформ сейчас большинством поддерживаются только pthreads (и то не весь зоопарк реализаций) и венда.

Cocoa NSThread? Не слышали?

Ну и да, почему-то весьма немало софтверных компаний пытается клепать мультиплатформенное ПО там, где это в эпоху тотальной виртуализации уже даром не нужно.

У разработчиков же, в том числе и у разработчиков ЯП, вообще какая-то фобия разработки под определённую платформу: дескать, «если я буду хорошо понимать, как это работает в Linux, но плохо понимать - как работает в Windows, то стану менее востребованным на рынке. Лучше я буду оперировать абстрактными понятиями в полном вакууме - и буду одинаково класть болт на все платформы, под которыми работает мой софт, потому что так оно спокойнее»

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Грин треды не про parallelism, они про concurrency. Если кто-то ожидает, что в параллельных задачах generic реализация гринтреды даст ощутимые плюсы (за исключением случаев нерегулярного общения, извиняюсь за самоизобретенный термин, то он делает это зря)

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

А насчёт затрат на переключение контекста - почему вдруг они выше с вашей точки зрения?

Если без учёта блокировок IO (предположим, все потоки просто выполняют долгоиграющие вычисления) контекст переключался, условно, 1 раз в 20 мс, то он так и будет переключаться раз в 20 мс, что здесь можно сэкономить.

Переключение контекста из 0-го кольца защиты в 3-е и обратно - не самая приятная задача конечно, но использование таймера как основного источника событий переключения не позволяет как-то гибко жонглировать количеством этих переключений в единицу времени.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Cocoa NSThread? Не слышали?

Но зачем, когда pthreads поддерживаются нативно?

WebKit на макоси использует pthreads, если бы у NSThread были хоть какие-то преимущества то полюбому бы их использовали

annulen ★★★★★
()
Ответ на: комментарий от qnikst

Запилил крохотный пример с тредами на Julia - на первом же @printf оно вывалилось в Segfault. Вот теперь охотно верю в то, что потоки «честные», pthread'овые. Так бы они сразу и сказали в документации, а то всё больше намёками вокруг, да около.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от qnikst

Раз ты тут оказался по случаю. Ты в курсе, что у вас reconnect не всегда работает? Хотя да, видел у вас issue. Собираетесь исправлять?)

Кстати, могу подкатить тест на основе своего кода полностью по BSD3

dave ★★★★★
()
Ответ на: комментарий от qnikst

В вопросе есть ложная дихотомия, нормально реализованные грин треды занимают все ядра, у них n рабочих OS процессов

Не понимаю. Совсем. Есть потоки исполнения, давайте говорить о них. Потоки исполнения в рамках одного процесса просто разделяют данные, таблицы страниц ОЗУ, у них один и тот же TSS.

Так вот, для того, чтобы «зелёные потоки» заняли несколько ядер - они должны работать в разных настоящих потоках исполнения pthreads. А после этого они уже, на мой взгляд, перестают быть таким уж зелёными, разве нет?

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от qnikst

Связь прямая: нижележащий код вывода на экран не является thread-safe. В рамках простого переключения кусков кода в одном потоке исполнения (кагбетредов), как это делает тот же python, никаких проблем с printf'ом бы не было, будь он хоть сколько угодно не safe.

DRVTiny ★★★★★
() автор топика
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от DRVTiny

pthreads не обязан создавать «честный» os thread (и не создаёт на некоторых os). Это бы только запутывало.

anonymous
()
Ответ на: комментарий от DRVTiny

А как вы такие потоки называете? Синими?

anonymous
()
Ответ на: комментарий от annulen

они и так человеческий вариант написания event loop.

qnikst ★★★★★
()

Отвечаю полность. Сразу извиняюсь, что писал про aнонiмуса, просто он любит делать вбросы в очень похожем стиле. Теперь к потокам:

1. Есть разные варианты маппинга грин тредов на реальные 1:1, N:1, N:M, все толковые языки реализуют N:M, причем OS треды могут быть разными в зависимости от нижележащей OS.

2. Да грин треды это не паралелизм, это concurrency, в том случае когда нужно сделать много разной работы при этом зачастую IO, а не CPU bound. В случае если просто параллелизм, то нету большого смысла делать больше рабочих процессов, чем ядер, все равно ось магию не совершит, а так хоть меньше переходов будет.

3. Соответсвенно в большинстве случаев грин треды это человеческое лицо к poll-интерфейсу, когда вместо лапши из колбеков/корутин пишется человеко-понятный код.

4. Несмотря на то, что green треды это про конкаренси, помочь параллелизму они тоже могут

5.

Как предполагается шарить данные между этими псевдопотоками, если они работают в рамках разных задач (процессов, если хотите).

green треды работают в рамках одного процесса, но могут выполняться в разных тредах, я не понимаю, в чем проблема с шареньем данных (если это не erlang).

6. да в грин тредах кооперативная многозадачность, но обычно задача переключения ложится на RTS. Делать можно по разному, например, в haskell передача управления происходит в safe points (аллокации), если истек таймер, или если тред «заблочился», на операции (для тредов многие операции выглядят блокируемыми), в связи с этим есть фишка в невозможности переключения процесса, который ничего не аллоцирует (с другой стороны компилятор сейчас умеет это решать).

7. Shared memory ортогонально потокам, и выполнению в разных тредах. Вопрос к библиотеке языка, все здоровые языки умеют (во всяком случае в библиотеках)

8.Грин треды не абстракция над OS тредами.

9. Когда ядро делает context switch, то ему нужно сделать много больше, сохранить/восстановить значения регистров, настроить страницы виртуальной памяти и т.п. По сравнению с программой, внутри которой переключение почти бесплатно. Так же каждый OS поток ест больше ресурсов системы, память записи в структуры данных и т.п. ~1000ns против 10?

10. С другой стороны RTS будет обязательно вносить свой оверхед и для задач, где надо тупо считать, а потом обменяться данными это может быть абсолютно бесполезно

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Кстати, https://docs.julialang.org/en/stable/manual/parallel-computing/

- звучит на удивление разумно. Редко в документации к ЯП можно увидеть что-то подобное. Особенно про эксклюзивный доступ ядра процессора к «своей» области памяти здорово написано.

DRVTiny ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.