Python多进程计算圆周率 Pi (π) 的值(ProcessPoolExecutor)
Posted Xavier Jiezou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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+14−8n+42−8n+51−8n+61)]
实验
设备
8 × Intel® Core™ i5-8300H CPU @ 2.30GHz 2.30 GHz
结果
迭代次数为 10000 时,进程池的不同最大进程数的耗时情况如下:(计算的 PI 值为 3.141592653589793)
进程池的最大进程数 | 耗时(评测 10 次,单位:秒) |
---|---|
1 | 53.55±1.98 |
2 | 42.17±1.49 |
4 | 28.01±0.77 |
8 | 21.73±0.51 |
16 | 19.93±0.48 |
32 | 20.51±0.37 |
61 | 22.65±0.84 |
备注:进程池的最大进程数必须小于或等于 61,否则会报错。
结论
从测试结果来看,进程池的最大进程数为 16 时,计算速度最快,耗时最短,比单进程快了两倍多;为 8 和 32 时,耗时也和 16 相差不多,32 以后耗时就变长了。因此,使用多进程编程时,一般进程池最大进程数设置为 CPU 的核心数就行。
参考
https://docs.python.org/3/library/concurrent.futures.html#processpoolexecutor
其它
多线程是不适合于计算密集型任务的,这里也评测了一下,结果如下:
线程池的最大线程数 | 耗时(仅评测 1 次,单位:秒) |
---|---|
1 | 48 |
2 | 47 |
4 | 55 |
源码
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__())
以上是关于Python多进程计算圆周率 Pi (π) 的值(ProcessPoolExecutor)的主要内容,如果未能解决你的问题,请参考以下文章