什么是Python多进程,如何实现?

什么是多进程

多进程用于执行多个进程的并行执行。

它可以帮助实现真正的并行性,因为可以同时执行不同的进程,并且每个进程都拥有自己的内存空间。

它使用CPU的独立核心,并且在执行进程间的数据交换时也很有帮助。

与多线程相比,多进程的计算成本更高,因为不使用共享内存空间。

不过,它允许进行独立执行,并克服了全局解释器锁的限制。

图片[1]-什么是Python多进程,如何实现?-不念博客

上图展示了一个多进程环境,在该环境中,一个主进程创建了两个独立的进程,并为它们分配了不同的工作。

多进程实现

目前对多线程及其实现方式和限制已经有基本的了解。现在,是时候学习多进程的实现以及如何克服这些限制了。

在这里将沿用相同的示例,但不再创建两个独立的线程,而是创建两个独立的进程,并讨论观察结果。

1、导入库:

from multiprocessing import Process
import os

本例将使用multiprocessing模块来创建独立的进程。

2、计算平方的函数:

该函数将保持不变。只是在这里删除了有关线程信息的打印语句。

def calculate_squares(numbers):
    for num in numbers:
        square = num * num
        print(
            f"Square of the number {num} is {square} | PID of the process {os.getpid()}"
        )

3、主函数:

主函数有一些修改。只是创建了一个独立的进程,而不是线程。

if __name__ == "__main__":
    numbers = [1, 2, 3, 4, 5, 6, 7, 8]
    half = len(numbers) // 2
    first_half = numbers[:half]
    second_half = numbers[half:]

    p1 = Process(target=calculate_squares, args=(first_half,))
    p2 = Process(target=calculate_squares, args=(second_half,))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

输出:

Square of the number 1 is 1 | PID of the process 1125
Square of the number 2 is 4 | PID of the process 1125
Square of the number 3 is 9 | PID of the process 1125
Square of the number 4 is 16 | PID of the process 1125
Square of the number 5 is 25 | PID of the process 1126
Square of the number 6 is 36 | PID of the process 1126
Square of the number 7 is 49 | PID of the process 1126
Square of the number 8 is 64 | PID of the process 1126

可以观察到,每个列表都由一个独立的进程执行,它们具有不同的进程ID。

为了检查进程是否已并行执行,需要创建一个单独的环境,下面我们将讨论这一点。

计算是否使用多进程的运行时间

为了检查是否获得了真正的并行性,在这里将计算使用和不使用多进程的算法运行时间。

为此,需要一个包含超过10^6个整数的大型整数列表。

可以使用random库生成一个列表,此处将使用Python的time模块来计算运行时间。

下面是实现的代码,代码本身很容易理解,也可以随时查看代码注释。

from multiprocessing import Process
import os
import time
import random

def calculate_squares(numbers):
    for num in numbers:
        square = num * num

if __name__ == "__main__":
    numbers = [
        random.randrange(1, 50, 1) for i in range(10000000)
    ]  # 创建一个包含10^7个整数的随机列表。
    half = len(numbers) // 2
    first_half = numbers[:half]
    second_half = numbers[half:]

    # ----------------- 创建单进程环境 ------------------------#

    start_time = time.time()  # 开始计时(不使用多进程)

    p1 = Process(
        target=calculate_squares, args=(numbers,)
    )  # 单进程P1执行整个列表
    p1.start()
    p1.join()

    end_time = time.time()  # 结束计时(不使用多进程)
    print(f"Execution Time Without Multiprocessing: {(end_time-start_time)*10**3}ms")

    # ----------------- 创建多进程环境 ------------------------#

    start_time = time.time()  # 开始计时(使用多进程)

    p2 = Process(target=calculate_squares, args=(first_half,))
    p3 = Process(target=calculate_squares, args=(second_half,))

    p2.start()
    p3.start()

    p2.join()
    p3.join()

    end_time = time.time()  # 结束计时(使用多进程)
    print(f"Execution Time With Multiprocessing: {(end_time-start_time)*10**3}ms")

输出:

Execution Time Without Multiprocessing: 619.8039054870605ms
Execution Time With Multiprocessing: 321.70287895202637ms

可以观察到,使用多进程的时间几乎是不使用多进程时间的一半。

这表明这两个进程在同一时间内并行执行,并展示了真正的并行性行为。

© 版权声明
THE END