当前位置:   article > 正文

(python加速)轻松学会多进程处理ProcessPoolExecutor

processpoolexecutor

前言

这个东西对于一些循环重复的操作,可以让你的程序加速好几倍,如果再加上编译的话,就更快了。所以,赶紧学起来吧。

判断素数

前言中的场景如下:我们需要判断100个数是否为素数,判断一个是否为素数的代码如下:

def is_prime(n):
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

判断100个数,无非就是循环而已,这种就特别适合使用多进程,并行计算,理论上提升100倍的速度,不过我们的计算机cpu核心数一般并没有100个,所以实际上无法并行100个进程。

假设我们要判断如下的100个超大数是否为素数:

PRIMES = [112272535095293] * 100
  • 1

ProcessPoolExecutor

from concurrent.futures import ProcessPoolExecutor
  • 1

由于我们是并行的进程,所以,先输出的结果不一定会是最开始运行的进程。那这样,我们岂不是会搞乱?无法分辨输出的结果是对应哪个的?

不会的,因为我们定义的时候,会定义好每一个进程的标识,输出的时候可以既打印进程标识,又打印对应结果,所以并不会搞乱。

定义的方法是字典,其中键是job(任务),任务的定义方式如下,使用submit,同时传入函数名称以及参数。然后值是我们的参数,其实这个值是我们随便定义的,不一定要是参数,之前我们不是说怕搞混吗?所以我们就填写参数作为进程标识。有人会问,job里面不是有n吗?这个不是已经是标识了嘛?问题是,我打印过job,不会显示n,而是一堆地址,你看不懂的。所以还是老实使用值来标识。

executor.submit(is_prime, n)#键
  • 1

完整定义如下:

 with ProcessPoolExecutor() as executor:
	jobs = {executor.submit(is_prime, n): n for n in PRIMES}
  • 1
  • 2

根据前面所说,值是随便定义的,所以当然可以如下:

jobs = {executor.submit(is_prime,n): "is_prime({})".format(n) for n in PRIMES}
  • 1

相当于更加可读了,更加标识这个进程。

as_completed

from concurrent.futures import as_completed
  • 1

上面执行了,我们需要打印结果。

    with ProcessPoolExecutor() as executor:
        jobs = {executor.submit(is_prime,n): "is_prime({})".format(n) for n in PRIMES}
        for job in as_completed(jobs):
            try:
                print("job:{},result:{}".format(jobs[job],job.result()))
            except Exception as e:
                print(e)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

部分结果如下:

job:is_prime(112272535095293),result:True
job:is_prime(112272535095293),result:True
job:is_prime(112272535095293),result:True
job:is_prime(112272535095293),result:True
job:is_prime(112272535095293),result:True

当然啦,我们100个素数由于都是一个数,所以打印出来一样,但是其实可以不一样。

我试过,我的笔记本是16核还是8核的,这个程序比正常的python程序挨个运行加速了3-4倍左右。

map

上面哪一个进程谁先执行完不知道,下面这个则是前面没完,后面的不会先完,后面的可能其实已经完了,但是前面没完,所以要等。速度不如上一节介绍的,大家看看就好。

     with ProcessPoolExecutor() as executor:
     try:
         results = executor.map(is_prime,PRIMES)
         for num, result in zip(PRIMES, results):
         print('fib(%s) result is %s.' % (num, result))
     except Exception as e:
         print(e)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/74849
推荐阅读
相关标签
  

闽ICP备14008679号