Сначала я исследовал и не смог найти ответа на свой вопрос. Я пытаюсь запустить несколько функций параллельно в Python.
У меня примерно так:
files.py
import common #common is a util class that handles all the IO stuff
dir1 = 'C:\folder1'
dir2 = 'C:\folder2'
filename = 'test.txt'
addFiles = [25, 5, 15, 35, 45, 25, 5, 15, 35, 45]
def func1():
c = common.Common()
for i in range(len(addFiles)):
c.createFiles(addFiles[i], filename, dir1)
c.getFiles(dir1)
time.sleep(10)
c.removeFiles(addFiles[i], dir1)
c.getFiles(dir1)
def func2():
c = common.Common()
for i in range(len(addFiles)):
c.createFiles(addFiles[i], filename, dir2)
c.getFiles(dir2)
time.sleep(10)
c.removeFiles(addFiles[i], dir2)
c.getFiles(dir2)
Я хочу вызвать func1 и func2 и запустить их одновременно. Функции не взаимодействуют друг с другом или с одним и тем же объектом. Прямо сейчас я должен дождаться завершения func1 до запуска func2. Как мне сделать что-то вроде ниже:
process.py
from files import func1, func2
runBothFunc(func1(), func2())
Я хочу иметь возможность создавать оба каталога примерно в одно и то же время, потому что каждую минуту я считаю, сколько файлов создается. Если каталога нет, это сбивает мое время.
Ответы:
Вы можете использовать
threading
илиmultiprocessing
.Из - за особенности CPython ,
threading
вряд ли достигнут истинного параллелизма. По этой причине,multiprocessing
как правило, лучше.Вот полный пример:
Механику запуска / присоединения дочерних процессов можно легко инкапсулировать в функцию в соответствии со строками вашего
runBothFunc
:источник
Это можно элегантно сделать с помощью Ray , системы, которая позволяет легко распараллеливать и распространять ваш код Python.
Чтобы распараллелить ваш пример, вам нужно будет определить свои функции с помощью
@ray.remote
декоратора, а затем вызвать их с помощью.remote
.Если вы передаете один и тот же аргумент обеим функциям, и аргумент имеет большой размер, более эффективный способ сделать это - использовать
ray.put()
. Это позволяет избежать двукратной сериализации большого аргумента и создания двух его копий в памяти:Если
func1()
иfunc2()
вернут результаты, вам нужно переписать код следующим образом:Использование Ray дает ряд преимуществ перед модулем многопроцессорной обработки . В частности, один и тот же код будет работать как на одной машине, так и на кластере машин. Чтобы узнать больше о преимуществах Ray, см. Этот пост .
источник
Если ваши функции в основном выполняют работу ввода-вывода (и меньше нагрузки на ЦП) и у вас есть Python 3.2+, вы можете использовать ThreadPoolExecutor :
Если ваши функции в основном выполняют работу процессора (и меньше операций ввода-вывода) и у вас установлен Python 2.6+, вы можете использовать модуль многопроцессорности :
источник
lambda: print('CPU task 1 running!'), lambda: print('CPU task 2 running!'),
добавления результатов к переменнымtask1_output
иtask2_output
Если вы являетесь пользователем Windows и используете python 3, то этот пост поможет вам выполнять параллельное программирование на python. При запуске программирования пула обычной многопроцессорной библиотеки вы получите сообщение об ошибке, касающееся основной функции в вашей программе. Это связано с тем, что в Windows нет функции fork (). Приведенный ниже пост дает решение упомянутой проблемы.
http://python.6.x6.nabble.com/Multiprocessing-Pool-woes-td5047050.html
Поскольку я использовал python 3, я немного изменил программу:
После этой функции приведенный выше код проблемы также немного изменится:
И я получил результат как:
Я думаю, что этот пост может быть полезен некоторым пользователям Windows.
источник
Невозможно гарантировать, что две функции будут выполняться синхронно друг с другом, что, кажется, именно то, что вы хотите сделать.
Лучшее, что вы можете сделать, - это разделить функцию на несколько шагов, а затем дождаться завершения обоих в критических точках синхронизации, используя
Process.join
подобные упоминания в ответе @ aix.Это лучше, чем
time.sleep(10)
потому, что вы не можете гарантировать точное время. При явном ожидании вы говорите, что функции должны быть выполнены, выполнив этот шаг, прежде чем переходить к следующему, вместо того, чтобы предполагать, что это будет выполнено в течение 10 мс, что не гарантируется в зависимости от того, что еще происходит на машине.источник
Похоже, у вас есть одна функция, которую нужно вызывать с двумя разными параметрами. Это можно элегантно сделать, используя комбинацию
concurrent.futures
иmap
с Python 3.2+.Теперь, если ваша операция связана с вводом-выводом, вы можете использовать
ThreadPoolExecutor
как таковой:Обратите внимание, как
map
здесь используетсяmap
ваша функция в списке аргументов.Теперь, если ваша функция связана с процессором, вы можете использовать
ProcessPoolExecutor
Если вы не уверены, вы можете просто попробовать оба варианта и посмотреть, какой из них дает лучшие результаты.
Наконец, если вы хотите распечатать свои результаты, вы можете просто сделать это:
источник