Как организовать распараллеливание внутреннего цикла в алгоритме на python?

#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);
  

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