Ответ 1
Когда очередь рабочего потока (или, в более общем смысле, любая очередь потоков) пуста, следует ли ее остановить, пока не будет что-то делать, или все в порядке, чтобы продолжать работать? Сопутствующие потоки занимают много вычислительной мощности, когда они не делают ничего, кроме наблюдения за своей очередью?
Вы должны использовать блокирующий вызов queue.get()
. Это оставит поток заблокированным при вводе-выводе, что означает, что GIL будет выпущен, и никакая вычислительная мощность (или, по крайней мере, минимальная сумма) не будет использоваться. Не используйте неблокирующие элементы в цикле while
, так как это потребует намного большего количества пробуждений процессора.
Должны ли быть объединены очереди двух потоков? Поскольку поток наблюдателя постоянно работает с одним методом, я думаю, что рабочий поток сможет просто вытаскивать задания из одной очереди, в которую помещается поток наблюдателя.
Если все наблюдатели делают это, вытягивая вещи из очереди и сразу же помещая их в очередную очередь, где ее потребляет один рабочий, это звучит как ненужные накладные расходы - вы можете просто просто потреблять ее непосредственно у рабочего, Это не совсем ясно для меня, если это случай, однако, является наблюдателем, потребляющим из очереди, или просто помещая элементы в один? Если он потребляет из очереди, кто вкладывает в него материал?
Я не думаю, что это будет иметь значение, поскольку я не многопроцессор, но эта настройка зависит от Python GIL (который, как я считаю, все еще существует в версии 3.4)?
Да, на это влияет GIL. Только один из ваших потоков может запускать байт-код Python за раз, поэтому не будет выполняться true parallelism, за исключением случаев, когда потоки запускают ввод-вывод (который освобождает GIL). Если ваш рабочий поток выполняет операции с привязкой к процессору, вы должны серьезно рассмотреть возможность запуска его в отдельном процессе через multiprocessing
, если это возможно.
Должен ли поток наблюдателя работать так непрерывно? Из того, что я понимаю, и, пожалуйста, исправьте меня, если я ошибаюсь, асинчио предполагается использовать для многопоточности на основе событий, что, по-видимому, имеет отношение к тому, что я пытаюсь сделать.
Трудно сказать, потому что я не знаю точно, что означает "работает непрерывно". Что он делает постоянно? Если он тратит большую часть своего времени на сон или блокировку на queue
, это прекрасно - обе эти вещи освобождают GIL. Если он постоянно выполняет фактическую работу, это потребует GIL и, следовательно, ухудшает производительность других потоков в вашем приложении (при условии, что они пытаются работать одновременно). asyncio
предназначен для программ, которые связаны с I/O, и поэтому их можно запускать в одном потоке с использованием асинхронного ввода-вывода. Похоже, ваша программа может быть хорошо подходит для этого в зависимости от того, что делает ваш worker
.
Основной поток в основном всегда просто ждет нажатия на клавишу для доступа к другой части меню. Это похоже на ситуацию, когда асинчио идеально подходит для, но, опять же, я не уверен.
Любая программа, в которой вы в основном ожидаете ввода-вывода, потенциально подходит для asyncio
- но только если вы можете найти библиотеку, которая делает проклятия (или любую другую библиотеку графического интерфейса, которую вы в конечном итоге выбираете), играйте с ней хорошо, Большинство графических интерфейсов имеют собственный цикл событий, который конфликтует с asyncio
. Вам нужно будет использовать библиотеку, которая может сделать цикл событий графического интерфейса отлично с циклом событий asyncio
. Вам также необходимо убедиться, что вы можете найти asyncio
-совместимые версии любой другой библиотеки на основе синхронного ввода-вывода, используемой вашим приложением (например, драйвер базы данных).
Тем не менее, вы вряд ли увидите какое-либо улучшение производительности, переключившись с вашей потоковой программы на что-то на asyncio
. Скорее всего, это будет примерно так. Поскольку вы имеете дело только с 3 потоками, накладные расходы на переключение между ними не очень значительны, поэтому переход от того, что однопоточный асинхронный подход ввода-вывода не будет иметь большого значения. asyncio
поможет вам избежать сложности синхронизации потоков (если проблема с вашим приложением - неясно, что она есть) и, по крайней мере теоретически, будет лучше масштабироваться, если ваше приложение потенциально нуждается в большом количестве потоков, но это не похоже подобный тот случай. Я думаю для вас, это в основном, к какому стилю вы предпочитаете вводить код (при условии, что вы можете найти все asyncio
-собираемые библиотеки, которые вам нужны).