您当前的位置: 首页 >  Python

Xavier Jiezou

暂无认证

  • 2浏览

    0关注

    394博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

Xavier Jiezou 发布时间:2021-08-25 22:14:45 ,浏览量:2

文章目录
  • 引言
  • 方法
  • 实验
    • 设备
    • 结果
  • 结论
  • 参考
  • 其它
  • 源码

引言

在上一篇文章中,给大家分享了使用蒙特卡罗法和公式法编写计算圆周率 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+14​−8n+42​−8n+51​−8n+61​)]

实验 设备

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

结果

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

进程池的最大进程数耗时(评测 10 次,单位:秒)153.55±1.98242.17±1.49428.01±0.77821.73±0.511619.93±0.483220.51±0.376122.65±0.84

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

结论

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

参考

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

其它

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

线程池的最大线程数耗时(仅评测 1 次,单位:秒)148247455 源码
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__())
关注
打赏
1661408149
查看更多评论
立即登录/注册

微信扫码登录

0.0402s