Параллельное программирование на Python (7): основное использование многопроцессорности и отличие от многопоточности

Python
Параллельное программирование на Python (7): основное использование многопроцессорности и отличие от многопоточности

процесс

так какGILСуществование многопоточности в Python на самом деле не многопоточность.Если вы хотите в полной мере использовать ее多核CPUресурсов, в большинстве случаев в Python нужно использовать многопроцессорность. Python предоставляет очень полезный многопроцессорный модуль.multiprocessing, просто определите функцию, а Python сделает все остальное. С помощью этого модуля можно легко перейти от одного процесса к параллельному выполнению.multiprocessingПоддерживает подпроцессы, обменивается данными и обменивается ими, выполняет различные формы синхронизации, обеспечиваетProcess,Lock,Queue,Pipeи другие компоненты.

  multiprocessingМодули — это многопроцессорные модули в Python. иthreading.ThreadТочно так же он может использоватьmultiprocessing.Processобъект для создания процесса. Процесс может запускать функции, написанные внутри программы Python. Объект Process используется так же, как и объект Thread, а также имеетstart(),run(), join()Методы. такжеmultiprocessingтакже в модулеLock/Event/Semaphore/Conditionкласс (эти объекты могут быть переданы в качестве параметров каждому процессу, подобно многопоточности), используемый для синхронизации процессов, его использование такое же, какthreadingОдноименный класс в модуле непротиворечив. так,multiprocessingбольшая частьthreadingИспользуйте тот же набор API, но переключитесь на ситуацию с несколькими процессами. Конечно, определение многопроцессорности аналогично определению многопоточности, то есть двумя способами:

Реализация целевой функции определяет новый процесс:

# 导入多进程模块
from multiprocessing import Process

# os.getpid() 获取当前进程的id
import os

def run_proc(name):
    print('{} child process is {}'.format(name, os.getpid()))

if __name__ == '__main__':
    print("Parent process is {}".format(os.getpid()))
    p = Process(target=run_proc, args=('test', ))
    print('child process will start...')
    p.start()
    p.join()

    print('child process end.')

Рабочий скриншот выглядит следующим образом:

运行截图

Унаследованные классы для определения новых процессов

from multiprocessing import Process
import os


class RunProc(Process):
    def __init__(self, name):
        Process.__init__(self)

        self.name = name

    def run(self):
        print('{} child process is {}'.format(self.name, os.getpid()))


if __name__ == "__main__":
    print("Parent process is {}".format(os.getpid()))
    p = RunProc('test')
    print('child process will start...')
    p.start()
    p.join()

    print('child process end.')

Результаты приведены ниже:

运行截图
Мы видим, что многопроцессорность используется почти так же, как и многопоточность, например: Процесс([группа [ цель [ имя [ аргументы [ kwargs]]]]])

  • group: группа потоков, еще не реализованная, подсказка в ссылке на библиотеку должна быть None;
  • цель: метод, который должен быть выполнен;
  • имя: имя процесса;
  • args/kwargs: аргументы для передачи методу.

Метод экземпляра:

  • is_alive(): возвращает, запущен ли процесс.
  • join([timeout]): блокировать процесс текущего контекста до тех пор, пока процесс, вызывающий этот метод, не завершится или не достигнет указанного времени ожидания (необязательный параметр).
  • start(): процесс готов, ожидая планирования ЦП
  • run(): start() вызывает метод run, если процесс-экземпляр не указан и передан вtarget,startвыполнить по умолчаниюrun()метод.
  • terminate(): немедленно остановить рабочий процесс, независимо от того, завершена задача или нет.

Атрибуты:

  • демон: и нитиsetDeamonта же функция
  • код выхода (Нет, когда процесс запущен, если это -N, это означает, что он завершается по сигналу N)
  • имя: имя процесса.
  • pid: идентификатор процесса.

Независимость процесса:

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

from multiprocessing import Process

# 测试数据
ex_list = 'Hello World'

# 修改数据进程
def revise_data():
    global ex_list

    # 修改全局变量
    ex_list = ex_list + ' with write revise_data process.'
    print('wirte result:', ex_list)

# 查看数据进程
def view_data():
    print(ex_list)

if __name__ == "__main__":
    process_revise = Process(target=revise_data)
    process_view = Process(target=view_data)

    process_revise.start()

    # 主进程等待写入进程执行完成以后代码 再继续往下执行
    process_revise.join()

    process_view.start()
    process_view.join()

    print("process end.")

Рабочий скриншот выглядит следующим образом:

运行结果
Мы определяем два процесса для изменения глобальных переменных и просмотра измененных данных соответственно.Мы видим, что, хотя измененный процесс успешно изменил переменные, глобальные переменные в процессе просмотра по-прежнему имеют исходное значение, то есть процесс Если глобальные переменные не являются общими, то есть создание подпроцесса фактически является копией основного процесса.Процессы независимы друг от друга, и доступ к глобальным переменным неодинаков, поэтому глобальные переменные не являются общими между процессами.