#python #multithreading
#python #многопоточность
Вопрос:
У меня есть 3-ступенчатая настройка производитель / потребитель.
Client
создает словари в кодировке JSON и отправляет их в PipeServer
через именованный канал
Вот мои потоки.Подклассы потоков:
PipeServer
создает именованный канал и помещает сообщения в очередь unprocessed messages
Processor
получает элементы из unprocessed messages
, обрабатывает их (через аргумент лямбда-функции) и помещает в очередь processed messages
Printers
получает элементы из processed messages
, получает блокировку, печатает сообщение и снимает блокировку.
В тестовом сценарии у меня есть один конвейерный сервер, один процессор и 4 принтера:
pipe_name = '\\.\pipe\testpipe'
pipe_server = pipetools.PipeServer(pipe_name, unprocessed_messages)
json_loader = lambda x: json.loads(x.decode('utf-8'))
processor = threadedtools.Processor(unprocessed_messages,
processed_messages,
json_loader)
print_servers = []
for i in range(4):
print_servers.append(threadedtools.Printer(processed_messages,
output_lock,
'PRINTER {0}'.format(i)))
pipe_server.start()
processor.start()
for print_server in print_servers:
print_server.start()
Вопрос: при такой многоступенчатой настройке, как мне продумать оптимизацию количества принтеров по сравнению Потоки процессора, которые у меня должны быть? Например, как мне узнать, является ли 4 оптимальным количеством потоков принтера? Нужно ли мне иметь больше процессоров?
Я прочитал документы по Python Profilers, но не увидел ничего, что помогло бы мне продумать такого рода компромиссы.
Ответ №1:
Вообще говоря, вы хотите оптимизировать максимальную пропускную способность вашего самого медленного компонента. В данном случае это звучит как клиент или принтер. Если это клиент, вам нужно достаточное количество принтеров и процессоров, чтобы иметь возможность обрабатывать новые сообщения (возможно, это только одно!). В противном случае вы будете тратить ресурсы на потоки, которые вам не нужны.
Если это принтеры, то вам нужно оптимизировать для происходящего ввода-вывода. Несколько переменных, которые следует учитывать:
- Сколько блокировок у вас может быть одновременно?
- Обязательно ли поддерживать блокировку на протяжении всей транзакции печати?
- Сколько времени занимает операция печати?
Если у вас может быть только одна блокировка, то у вас должен быть только один поток, и так далее, и тому подобное.
Затем вы хотите протестировать в реальном мире (трудно предсказать, какая комбинация оперативной памяти, диска и сетевой активности замедлит вашу работу). Обработайте свой код, чтобы вы могли видеть, сколько потоков простаивает в любой момент времени. Затем создайте тестовый пример, который обрабатывает данные в системе с максимальной пропускной способностью. Начните с произвольного количества потоков для каждого компонента. Если потоки клиента, процессора или принтера всегда заняты, добавьте дополнительные потоки. Если некоторые потоки всегда простаивают, удалите некоторые.
Возможно, вам потребуется перенастроить, если вы переместите код в другую аппаратную среду — разное количество процессоров, больше памяти, другой диск — все это может оказать влияние.