Можно ли распараллелить несколько цепочечных генераторов на нескольких ядрах процессора? - PullRequest
2 голосов
/ 11 января 2020

При стандартном CPython невозможно по-настоящему распараллелить выполнение программы на нескольких ядрах ЦП, используя threading . Это связано с Глобальной блокировкой интерпретатора (GIL) .

CPython подробности реализации: In CPython, из-за глобальной блокировки интерпретатора только один поток может выполнить код Python одновременно (даже если некоторые ориентированные на производительность библиотеки могут преодолеть это ограничение). Если вы хотите, чтобы ваше приложение лучше использовало вычислительные ресурсы многоядерных машин, рекомендуется использовать multiprocessing или concurrent.futures.ProcessPoolExecutor. Тем не менее, многопоточность по-прежнему является подходящей моделью, если вы хотите запустить несколько задач, связанных с вводом / выводом одновременно.

Источник: CPython Документация

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


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

Хотя этот алгоритм довольно быстрый, я спрашиваю себя, можно ли его распараллелить с многопроцессорной обработкой Pythons, поэтому каждый генератор работает одно ядро ​​процессора. Я думаю, что между двумя генераторами (производитель / потребитель) для разделения скоростей исполнения потребуется какой-то буфер / FIFO.

Мои вопросы:

  • Возможна ли такая реализация?
  • Как будет выглядеть минимальный пример?

tokenStream = Token.GetGenerator(fileContent)           # producer
blockStream = Block.TranslateTokenToBlocks(tokenStream) # consumer / producer
groupStream = Group.TranslateBlockToGroup(blockStream)  # consumer / producer
CodeDOM =     CodeDOM.FromGroupStream(groupStream)      # consumer
...