Pull to refresh

Comments 12

Спасибо за перевод. Вопрос: если я не сторонник внутрипитоновской мультипроцессности, а распараллеливание вычислений делаю микросервисной архитектурой (есть диспетчер и есть одинаковые воркеры, которые запускаются в некоторых количествах на одном или на нескольких серверах), то существует ли способ внутри питоновской программы принудительно указать какое логическое ядро я хочу использовать? Например, имеем 16 ядер, запускаем 16 воркеров, смотрим на загрузку- 15 ядер загружены, а одно- нет — значит работа идет не оптимальная- 16 программ работаеют на 15ти ядрах. Хочется иметь возможность принудительно указать воркеру номер ядра на котором он будет исполняться. Интересуют ваши соображения по этому поводу как для линукса так и для винды. Заранее признателен за ответ.
В случае с Unix системами можно попробовать поиграться с os.sched_setaffinity. Если же Вы видите неравномерную нагрузку на ядра ЦПУ, то это скорее не проблема Python или Вашего приложения, это проблема ОС и ее планировщика.
Да, именно так. Это проблема планировщика ОС, который раскидывает задачи по ядрам. И когда он это делает не оптимально (для меня) — хочется вмешаться и явно сказать что и на каком ядре запускать.
И когда он это делает не оптимально (для меня) — хочется вмешаться и явно сказать что и на каком ядре запускать.
Выглядит очень странно. Операционка обычно равномерно нагружает ядра. Возможно ваши воркеры никогда не завершаются, и тогда у операционки нет возможности перераспределить нагрузку. Простым решением в вашем случае должен быть запуск каждой поступающей задачи в новом потоке, и завершать поток при завершении задачи. Но это не точно.

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

Равномерное распределение по ядрам достигается путем повышения гранулярности задач и использования архитектуры очередь-воркеры. То есть вам не нужно отдавать воркеру слишком жирную задачу, иначе когда другие воркеры освободятся, этот воркер не поделится с ними этой задачей. Нужно разбивать задачку на чанки, их скармливать в очередь, а из очереди воркерами эти чанки забирать.

В случае микросервисной архитектуры, сервисы могут забирать чанки из любого брокера сообщений (kafka, rabbit, etc). В случае питоновских потоков/процессов сгодятся встроенные очереди из стандартной библиотеки. Так же питон предоставляет сетевые очереди через Manager, к которым можно подключаться из других процессов питона.

и почему перезапущенный воркер будет работать более оптимально, если при предыдущем запуске он работал не так..

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

Как вариант использовать psutil и его Process.cpu_affinity

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

Ну видимо да. Я подергался и успокоился. При современной дешевизне бушных Xeon-ов особых проблем нет пока.

а теперь вместо потоков попробовать использовать event-driven engine, тот же Twisted
я не опнял первый пример. Без потоков получилось 135 милисекунд, с потоками получилось 147. И в выводах пишут что это успех. Но ведь стало медленнее???

Хорошо было бы добавить обзор asyncio, а ещё лучше, сравнить многопоточность и event loop для задач ввода-вывода.

Sign up to leave a comment.