Comments 21

У меня есть пара глупых вопросов.


Что автор понимает под многоядерностью в Python? Разве процессы не распределяются планировщиком на различные ядра?


Что мы видим на Python? Один процесс на задачу, в Python до сих пор нет мультикора.

Какой код должны выполнять несколько процессов, если задача одна?


всё так же сложно сделать многоядерность.

Так всё же сложно сделать или она вообще отсутствует?

Задача никогда не бывает одна. Точнее не так.
Например, обработка запросов от 1000 клиентов. Это 1 задача? Или 1000 задач?
А представьте себе, что поток выполнения один, а обработка клиента не очень быстрая (скажем, cpu bound).


Так всё же сложно сделать или она вообще отсутствует?

asyncio — это не про настоящую многопоточность. И Вы сами это знаете. Поэтому если нужно наращивать производительность — надо комбинировать и многопоток, и асинхронщину. А в python — первое — это боль. И асинхронщина никак эту боль не снимает. А какие варианты? Либо ждать у моря погоды, либо комбинировать подходы, либо искать более лучшие языки (golang? Erlang?)

asyncio — это не про настоящую многопоточность. И Вы сами это знаете.

Да, знаю. Но мой вопрос не про многопоточность или асинхронность.


Мне непонятно, что именно автор понимает под многоядерностью в Python. В Python можно создавать процессы? Можно. Процессы работают на разных ядрах? Работают. Почему утверждается, что в Python нет многоядерности. И как вообще язык должен поддерживать многоядерность кроме как через примитивы операционной системы?


Ещё раз повторю, я сейчас об определении самого понятия «многоядерность в Python», которое автор использует, а не о том, насколько эффективно можно на чистом Python нагружать ядра.

Правильно! Работать надо, а не комментить! Ведь всегда в интернете найдется тот, кто будет неправ!

Потому что интерпретатор работает в однопоточном режиме (и опять же — Вы сами это знаете). GIL и это вот все. И другого способа, кроме как инстанцировать НОВУЮ копию интерпретатора и общаться с ней, как Вы правильно заметили, через существующие примитивы ОС — нет. А это малоэффективно. Внезапно, но многопоточность даже в Си/C++ будет эффективнее работать, как минимум, потому что нет интерпретатора с необходимостью поддерживать консистентность глобального стейта. А идеальная ситуация — когда как в голанге — язык уже изначально форсит работу в легких потоках и обмен сообщениями между ними. На уровне ядра языковых конструкций. Что и позволяет этому всему превращаться в эффективный и максимально безопасный (насколько это возможно) код.

Спасибо за подробные ответы, но я лишь хотел узнать, что автор понимает под отсутствием многоядерности в Python. Я не рассчитывал на продолжительную дискуссию. Мне достаточно было бы ответа вроде «это работа интерпретатора в однопоточном режиме». Потому что «многоядерность в Python» можно понимать по-разному.

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

Тут есть нюансы (которые упомянул bvm84 чуть ниже):


  • Python – это не только CPython,
  • программа на Python может использовать модули с нативным кодом, в которых нет GIL (ведь вы же о нём, в основном?).

Не Cypthon-ном единым жив Python. Если GIL есть проблема — существуют реализации спеки Python без него. Функциональный подход хорош, но Python это зачастую обертка с приятным синтаксисом вокруг чего-то более специфичного. Тот же openblas написан на C и крошит матрицы во все ядра и потоки, а numpy/scipy оборачивает его в доступный api. Опять же если в голанге работа с потоками уже сделано хорошо, проще сделать обертку вокруг хорошо работающей вещи, чем пилить ведосипед. На мой взгляд Python стремится идти таким путём, и для его круга задач это правильно. Кому сильно нужны фичи Elixira возьмет и выучит его.

Это очень интересный вопрос. И если Вам есть что рассказать — с радостью послушаю.
Единственное, что могу добавить по поводу numpy/openblas — это то, что это не очень хорошо прыгать из одной экосистемы в другую, т.к. фактически мы очень ограниченно исправляем недостатки одной, а при этом добавляем фрагментарности. Не удивительно, что иногда всё-таки появляются нативные python реализации каких-либо библиотек (напр., hdfs3 для Питона), потому что стыковать и доставлять программные модули из разных миров… достаточно сложная и хрупкая работа. Тем более — на разных архитектурах.


. На мой взгляд Python стремится идти таким путём, и для его круга задач это правильно.

Допускаю. Иначе он не стал бы таким популярным инструментом.

Python – прекрасный язык-клей, который очень удобен для соединения модулей на нативном коде. Если взять машинное обучение или анализ данных, где Python стал популярным, так там и вовсе в программах, формально считающихся, что они написаны на Python, большую часть времени работает именно нативный код библиотек.

Потоки были созданы с надеждой, что все будет легко, просто и весело. Сейчас мультипотоковое программирование считается антипаттерном. Если бизнес-логика написана на потоках — этот код, скорее всего, надо выбросить, потому что в нем наверняка есть ошибки. Если вам кажется, что ошибок нет, значит вы просто их еще не нашли.

Вот это, блин, новость. Ну правильно, если нет у тебя вменяемой поддержки тредов, то давайте объявим треды злом. JS уже бежит следом, радостно поддакивая.

Что такое вменяемая поддержка тредов? Я почти наверняка уверен, что даже с настоящими тредовыми языками — все равно будут проблемы с синхронизацией потоков, общим стейтом, дедлоками и гоночками. Разве не так ?

Вменяемая поддержка тредов это точно не как GIL в пайтоне.

Проблемы с синхронизацией, дедлоками и гоночками отлично можно получить и на нескольких процессах, зависит от самой логики приложения — то ли вы выполняете тысячи маленьких запросов которые не имеют друг к другу никакого отношения (типовое апи для веба, например, там воркеры отлично работают), то ли вы хотите распараллелить выполнение какой-то одной ресурсоемкой задачи.
Имхо, у автора спутано теплое с мягким — антипаттерном я бы называл ручное управление потоками (непосредественное использование низкоуровнего API операционных систем). А сами потоки вполне хорошо работают в реализациях высокоуровневых конструкций и их использование вполне себе best practices.
Elixir и Phoenix оставили приятные впечатления. Быстрый старт, только первое время тяжеловато воспринимать конвееры, неизменяемое состояние. Небольшой проект, сделал за 10 дней с нуля (fast and dirty) здесь.

"все остальное уже реализовано в Erlang: работа с сетью, обработка HTTP и веб-сокетов, работа с базами данных"
Спасибо, посмеялся. Там уже завезли поддержку unicode strings?
В Erlange даже http-реквесты нормально сделать проблема :) Дрова к базам сплошь кривые да устаревшие. Слишком маленькое коммюнити, некому и не для кого писать.
Желающему что-то реализовать на ерланге придется непрерывно заниматься велосиподостроением. Но статья хорошая! Всегда полезно сравнивать.

Скорее всего вы отстали лет на пять-семь.


Загляните в Hex с его десятком тысяч пакетов и попробуйте прикинуть на вашем текущем проекте к примеру — какой процент недостающих пакетов был бы, если бы вы писали его на Эликсире?


(Если вы действительно озаботитесь этим, скиньте пожалуйста название этих пакетов — у меня есть карманная армия велосипедостроителей, которая уже завтра их напишет)

Я не помню точно, но вроде бы эрланг тоже кооперативную многозадачность реализует, совершая переключение при превышении количества выделенных на исполнение процесса редукций. Причем, переключается при вызове функции, а если учесть, что рекурсия — единственный способ в эрланге сделать цикл, то в принципе эта модель становится близка к преемптивной.

Вдруг кому интересно.
Only those users with full accounts are able to leave comments. Log in, please.