#python-3.x #multithreading #algorithm #multiprocessing
#python-3.x #многопоточность #алгоритм #многопроцессорность
Вопрос:
Я начал изучать программирование. Как распараллелить внутренний цикл в алгоритме? Алгоритм суммирования элементов
def SumFunc(array):
y = array
m = len(array)
while m != 1:
i = 0
j = m - 1
while i < j:
y[i] = y[i] y[j]
i = i 1
j = j - 1
m = int((m 1) / 2)
return y[0]
if __name__ == '__main__':
numbers = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
print(SumFunc(numbers))
Комментарии:
1. Внутренний цикл требует последовательной обработки. Я не понимаю, как вы выполняете несколько операций одновременно. Может быть, лучше разделить исходный список и просуммировать каждый вложенный список одновременно, затем объединить в новый список и перезапустить.
2. Даже опытные программисты испытывают трудности с распараллеливанием кода. В качестве пути обучения я бы рекомендовал сначала сосредоточиться на последовательной обработке и удобочитаемости кода.
Ответ №1:
Вы можете распараллелить внутренний цикл, выяснив его «размер итерации» — насколько большой интервал он фактически проходит. Он выполняет m // 2
шаги, и вы записываете только в самую первую часть массива (с индексом 0) и считываете с противоположной стороны.
У вас есть подзадача: добавить к числу с этим индексом номер с противоположной стороны (с тем же смещением)
Эти подзадачи можно сгруппировать (сделайте это для индексов от некоторого A до B). Группы независимы, поэтому их можно выполнять параллельно. Вероятно, вам следует создать количество групп ~ равное количеству ядер. Эти группы должны равномерно покрывать ваш интервал индексов.
Это будет ваша группа подзадач:
for i in range(i_from, i_to):
array[i] = array[end - i]
Ваша замена внутреннего цикла может выглядеть примерно так:
INTERVAL_SIZE = m // 2
for core in range(N_CORES):
end = m - 1
i_from = (core * INTERVAL_SIZE) // N_CORES
i_to = ((core 1) * INTERVAL_SIZE) // N_CORES)
THREAD_POOL[core] = ... # start doing the task with given args
# join later
Пример:
У вас есть массив: [1, 2, 3, 4, 5, 6]
с 2 ядрами.
initial m = 6;
Create thread-pool of size 2;
...
INTERVAL_SIZE is 3;
Split it between 2 cores:
Group 1: Indexes in range(0, 1) => [0]
Group 2: Indexes in range(1, 3) => [1, 2]
Execute group-tasks in parallel;
Wait until everything is finished (join);
Очевидно, что есть места для улучшения, но это основная идея, которую вы могли бы попробовать. Лично я бы попробовал другой подход к вашей проблеме, если это возможно.