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

Новое для python, и я хочу выполнить параллельное программирование в следующем коде и хочу использовать многопроцессорность в python для этого. Итак, как изменить код? Я искал метод с помощью пула, но нашел ограниченные примеры, за которыми я могу следовать. Кто-нибудь может мне помочь? Спасибо.

Обратите внимание, что setinner и setouter – это две независимые функции, и я хочу использовать параллельное программирование для сокращения времени работы.

def solve(Q,G,n): i = 0 tol = 10**-4 while i < 1000: inneropt,partition,x = setinner(Q,G,n) outeropt = setouter(Q,G,n) if (outeropt - inneropt)/(1 + abs(outeropt) + abs(inneropt)) < tol: break node1 = partition[0] node2 = partition[1] G = updateGraph(G,node1,node2) if i == 999: print "Maximum iteration reaches" print inneropt 

  • Можно ли __setattr __ () определить в классе с __slots__?
  • Как перебирать первые n элементов списка?
  • Параметр «chunksize» в многопроцессорной обработке Python.Pool.map
  • Практические примеры использования NLTK
  • py2exe / pyinstaller и DispatchWithEvents
  • Python Scrapy - заполнить start_urls из mysql
  • Как поместить переменную в docstring Python
  • Зачем использовать оператор return в Python?
  • One Solution collect form web for “Как использовать многопроцессорность в python”

    Трудно распараллелить код, который должен мутировать одни и те же общие данные из разных задач. Итак, я собираюсь предположить, что setinner и setouter являются не мутирующими функциями; если это не так, все будет сложнее.

    Первый шаг – решить, что вы хотите делать параллельно.


    Одна очевидная вещь – сделать setinner и setouter одновременно. Они полностью независимы друг от друга, и всегда нужно, чтобы оба делались. Итак, вот что я сделаю. Вместо этого:

     inneropt,partition,x = setinner(Q,G,n) outeropt = setouter(Q,G,n) 

    … мы хотим представить две функции в качестве задач в пул, а затем дождаться, когда оба будут выполнены, а затем получить результаты обоих.

    Модуль concurrent.futures (для которого требуется сторонний backport в Python 2.x) упрощает выполнение таких действий, как «дождаться, когда это будет сделано», чем модуль multiprocessing (который находится в stdlib в версии 2.6+), но в этом случае нам ничего не нужно; если один из них заканчивается рано, нам нечего делать, пока другой не закончит все равно. Итак, давайте придерживаться multiprocessing.apply_async :

     pool = multiprocessing.Pool(2) # we never have more than 2 tasks to run while i < 1000: # parallelly start both tasks inner_result = pool.apply_async(setinner, (Q, G, n)) outer_result = pool.apply_async(setouter, (Q, G, n)) # sequentially wait for both tasks to finish and get their results inneropt,partition,x = inner_result.get() outeropt = outer_result.get() # the rest of your loop is unchanged 

    Возможно, вы захотите переместить пул вне функции, чтобы он жил вечно и может использоваться другими частями вашего кода. А если нет, вы почти наверняка захотите закрыть пул в конце функции. (Более поздние версии multiprocessing позволяют вам просто использовать пул в операторе with , но я думаю, что для этого требуется Python 3.2+, поэтому вам нужно сделать это явно.)


    Что делать, если вы хотите больше работать параллельно? Ну, здесь нет ничего более очевидного без перестройки цикла. Вы не можете делать updateGraph пока не получите результаты от setinner и setouter , и здесь ничего не медленнее.

    Но если бы вы могли реорганизовать вещи так, чтобы каждый из setinner был независим от всего, что было раньше (что может или не возможно с вашим алгоритмом – не зная, что вы делаете, я не могу догадаться), вы можете нажать 2000 задач на очередь впереди, затем цикл, просто хватая результаты по мере необходимости. Например:

     pool = multiprocessing.Pool() # let it default to the number of cores inner_results = [] outer_results = [] for _ in range(1000): inner_results.append(pool.apply_async(setinner, (Q,G,n,i)) outer_results.append(pool.apply_async(setouter, (Q,G,n,i)) while i < 1000: inneropt,partition,x = inner_results.pop(0).get() outeropt = outer_results.pop(0).get() # result of your loop is the same as before 

    Конечно, вы можете сделать этого фаворита.

    Например, допустим, вам редко нужно больше пары сот итераций, поэтому расточительно всегда вычислять 1000 из них. Вы можете просто нажать первый N при запуске и проталкивать еще один раз через цикл (или больше N раз в N раз), чтобы вы никогда не делали больше, чем N потраченных итераций – вы не можете получить идеальный компромисс между идеальным параллелизмом и минимальным отходов, но вы можете настроить его довольно красиво.

    Кроме того, если задачи на самом деле не так долго, но у вас их много, вы можете их загрузить. Один очень простой способ сделать это – использовать один из вариантов map вместо apply_async ; это может сделать ваш выборку кода немного сложнее, но делает код очереди и пакетный код тривиальным (например, для map каждой func по списку из 100 параметров с помощью chunksize of 10 всего две простые строки кода).

    Python - лучший язык программирования в мире.