Добавьте элемент в список с помощью многопроцессорного python

#python #multithreading #concurrency #multiprocessing

Вопрос:

Я определил функцию, которая принимает ввод одного целого числа и возвращает выходное целое число.

 def get_output(n):
  output = # process the integer
  return output
 

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

 input_list = [1,2,3,5,6,8,5,5,8,6,5,2,5,2,5,4,5,2]
 

Теперь я определил пустой список вывода, в котором будут храниться выходные данные функции.

 output_list = []
 

Теперь я хочу просмотреть каждый отдельный пункт input_list и добавить его в output_list . Я знаю, как добиться этого последовательным способом, но я хочу знать, как распараллелить эту задачу.
Заранее спасибо.

Комментарии:

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

2. @Andrew-Харельсон да, я пытаюсь добиться максимальной эффективности, но не смог этого понять

3. Является ли ваш шаг «обработать целое число» интенсивным для процессора или ввода-вывода? Если нет, выполнение этого последовательно будет быстрее, чем параллельно. Если да, то является ли это более интенсивным процессором или более интенсивным вводом-выводом? Я могу дать ответ, но лучший способ сделать это зависит от процессора и ИО связан.

Ответ №1:

IIUC вам нужен:

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

Потоки более интенсивно используют ввод-вывод, поэтому, если это то, что вам нужно, вы можете попробовать:

 from concurrent.futures import ThreadPoolExecutor
def get_output(n):
    output = n ** 2
    return output

input_list = [1,2,3,5,6,8,5,5,8,6,5,2,5,2,5,4,5,2]
output_list = []

if __name__ == '__main__':
    with ThreadPoolExecutor(max_workers=6) as pool:
        output_list.extend(pool.map(get_output, input_list))
        
print(output_list)
 

Это обрабатывает список и помещает все элементы в квадраты, он применяет это к 6 элементам параллельно, как вы можете видеть, я указал max_workers=6 .

Если ваш целочисленный процесс больше привязан к процессору, используйте многопроцессорную обработку.

С практически тем же кодом:

 from concurrent.futures import ProcessPoolExecutor
def get_output(n):
    output = n ** 2
    return output

input_list = [1,2,3,5,6,8,5,5,8,6,5,2,5,2,5,4,5,2]
output_list = []

if __name__ == '__main__':
    with ProcessPoolExecutor(max_workers=6) as pool:
        output_list.extend(pool.map(get_output, input_list))
        
print(output_list)
 

Это делает то же самое, он обрабатывает и квадраты всех элементов для каждых 6 элементов попарно.

Вывод обоих кодов:

 [1, 4, 9, 25, 36, 64, 25, 25, 64, 36, 25, 4, 25, 4, 25, 16, 25, 4]
 

Комментарии:

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

2. @Darkknight Это зависит от того, я думаю, что это лучший способ… Для обработки целых чисел вам также следует изучить функции numpy, чтобы сделать это, потому что серверная часть numpy находится на языке C, поэтому она работает быстрее.

3. да, я знаю, что я просто задаю этот вопрос, чтобы получить четкое представление о том, что фактическая функция отличается, поэтому я попробую это сделать и дам вам знать, как она работает при многопроцессорной обработке. Еще раз спасибо

Ответ №2:

Сначала добавьте выходные данные в «список ввода».

 output_list = numpy.zeros_like(input_list)
output_list  = input_list
 

Здесь происходит программирование массивов.

Комментарии:

1. Это просто копирует список, и если вы проверите время выполнения, это также примерно в 10 раз медленнее, чем просто использование list() в качестве копира. Кроме того, в своих тестах я наблюдаю довольно незначительный параллелизм процессорного времени.

2. @Andrew-Harelson Я использовал программирование массивов. Это удивляет, если существует очень большой массив, и у вас есть некоторые серьезные вычисления, связанные с массивом(например, A1 = A1 3*A2). Тем не менее, спрашивающий может использовать list (), если он работает быстрее, потому что работа здесь проста.