【Python】多进程计算圆周率 Pi (π) 的值(ProcessPoolExecutor)


引言

上一篇文章中,给大家分享了使用蒙特卡罗法和公式法编写计算圆周率 Pi (π) 的 Python 代码。但发现了一个问题,计算速度很慢。计算圆周率属于计算密集型任务(也叫CPU密集型任务),区别于 IO 密集型任务,即 CPU 占用较大,而数据传输或磁盘等占用较小。对于 CPU 密集型任务,使用多进程能充分使用 CPU 的多个核心,极大地提高计算速度。

方法

使用如下公式计算圆周率 Pi (π) 的值:
π = ∑ n = 0 ∞ [ 1 1 6 n ( 4 8 n + 1 − 2 8 n + 4 − 1 8 n + 5 − 1 8 n + 6 ) ] \pi = \sum_{n=0}^\infty [\frac{1}{16^n}(\frac{4}{8n+1}-\frac{2}{8n+4}-\frac{1}{8n+5}-\frac{1}{8n+6})] π=n=0[16n1(8n+148n+428n+518n+61)]

实验

设备

8 × Intel® Core™ i5-8300H CPU @ 2.30GHz 2.30 GHz
在这里插入图片描述

结果

迭代次数为 10000 时,进程池的不同最大进程数的耗时情况如下:(计算的 PI 值为 3.141592653589793)

进程池的最大进程数耗时(评测 10 次,单位:秒)
153.55±1.98
242.17±1.49
428.01±0.77
821.73±0.51
1619.93±0.48
3220.51±0.37
6122.65±0.84

备注:进程池的最大进程数必须小于或等于 61,否则会报错。

结论

从测试结果来看,进程池的最大进程数为 16 时,计算速度最快,耗时最短,比单进程快了两倍多;为 8 和 32 时,耗时也和 16 相差不多,32 以后耗时就变长了。因此,使用多进程编程时,一般进程池最大进程数设置为 CPU 的核心数就行。

参考

https://docs.python.org/3/library/concurrent.futures.html#processpoolexecutor

其它

多线程是不适合于计算密集型任务的,这里也评测了一下,结果如下:

线程池的最大线程数耗时(仅评测 1 次,单位:秒)
148
247
455

源码

import concurrent.futures as cf
from tqdm import tqdm
import os


class CalculatePI(object):
    """Calculate the value of π by multi process

    Args:
        num_iterations (int): Number of iterations. Default: 100000
        max_workers (int): Maximum number of processes. Default: the number of processors on the machine.
    """

    def __init__(self, num_iterations: int = 100000, max_workers: int = os.cpu_count()) -> None:
        """Initialization

        Args:
            num_iterations (int): Number of iterations. Default: 100000
            max_workers (int): Maximum number of processes. Default: the number of processors on the machine.
        """
        self.num_iterations = num_iterations
        self.max_workers = max_workers

    def __calc__(self, start: int, end: int) -> float:
        """Calculate the value of π according to formula

        Args:
            start (int): Starting value for the iterations
            end (int): Ending value for the iterations

        Returns:
            float: Value of π
        """
        PI = 0
        for n in tqdm(range(start, end)):
            PI += 1/pow(16, n) * (4/(8*n+1) - 2 / (8*n+4) - 1/(8*n+5) - 1/(8*n+6))
        return PI

    def __main__(self) -> float:
        """Calulate the value of π by multi process

        Returns:
            float: Value of π
        """
        PI = 0
        with cf.ProcessPoolExecutor(self.max_workers) as p:
            futures = []
            for i in range(self.max_workers):
                start = i*self.num_iterations//self.max_workers
                end = (i+1)*self.num_iterations//self.max_workers
                futures.append(p.submit(self.__calc__, start, end))
            for future in cf.as_completed(futures):
                PI += future.result()
        return PI


if __name__ == '__main__':
    print(CalculatePI().__main__())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xavier Jiezou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值