python 任务管理,Python 多任务
随着计算机技术的发展,GPU和超级计算平台非常发达。但是这些技术的本质并没有带来算法的创新,能够提高计算的速度和规模,很大程度上得益于分布式计算和并行计算的优势。本节介绍一个名为concurrent的工具,它用于在简单的python中实现多进程代码。还介绍了如何更好地配置多进程资源。
concurrent use instance concurrent是python自带的多进程实现库,不需要其他安装。首先,这里是一个没有多进程的示例代码。
# sleep . pyimporttimedefsleep(seconds):time . sleep(seconds)if _ name _= _ main _ 3360 timme fortin dings:{ } s 。format (time 1-time 0)))这个代码的作用其实就是睡眠110。
on[de chin @ de chin-manjaroconcurrent]$ python 3 sleep。皮蒂梅科斯蒂28601 . 688888888686
假设上面程序的sleep函数运行一个需要1s的计算任务,而不是暂停1s。有很多CPU,我们希望加快这个计算过程。此时就需要多工艺技术了。下面是改成多进程的代码。
# concurrent _ sleep . pyimportconcurrent . futuresimporttimedefsleep(秒)3360 time.sleep(秒)if _ name 1110 pool executor))as executor:executor . map)sleep,times(time 1=time . time))print( thetimecostis 3360 { } s),即concur原代码的for循环。
根据[de chin @ de chin-manjaroconcurrent]$ python 3 current _ sleep . python etimecostis:0304219722747803s的结果,运行时间为10s。为什么优化后不是3s或1s而是2s,将在下一章解释。
多进程最优配置使用多进程方案,加速效果很大程度上取决于硬件。理论上,如果有n个cpu核,可以加速n倍。但在大多数情况下,受限于算法和任务本身,与N倍加速有一定差距。首先,让我们使用ipython来查看本地计算机上有多少个CPU:
[de chin @ de chin-manjaroconcurrent]$ ipython python 3 . 8 . 5(默认,sep 42020,07:14)type copyright core for help . in[1]:importpsutil[2]:psutil . CPU _ count(logical=false)out[2]:4in[3]3360 psutint这是因为可以更好地区分逻辑核心和物理核心。我们的本地计算机有四个物理核,每个物理核实际上对应两个逻辑核,所以总共有八个逻辑核。也就是说,理论上算法执行时间最多可以加速8倍。尝试配置和修改一些测试和验证参数。
# concurrent _ sleep . pyimportconcurrent . futuresimporttimeimportsysdefsleep(秒):time.sleep)秒(如果)
] * int(sys.argv[2]) #以concurrent . futures . processpoolexecutor()为执行器获取时间输入参数time 0=time . time():executor . map(sleep,Times) time1=time.time () print(时间开销为:{} s 。格式(时间1-时间0))。本例中,为了调整方便,我们将总睡眠时间设置为命令行的输入参数,使用函数sys.argv来获取。注意,获得的参数是字符串格式的。该字符串代码的执行方法和结果如下:
[de chin @ de chin-man jaro concurrent]$ python 3 current _ sleep . py-t16时间开销为:2.0304934978485107s在上面的执行结果中,我们发现原本需要16s的睡眠任务在多进程场景下加速到2s,正好符合我们对逻辑核加速倍数的预期。但是,如前所述,逻辑核的倍数能否加速,还与任务本身的算法有关。例如,在这个用例中,如果算法分配的结果是需要17个子算法来实现它,那么在每个逻辑核执行了两次睡眠任务之后,另一个逻辑核需要再执行一次睡眠任务,而其他逻辑核需要等待执行该任务的逻辑核的任务结束。具体实施结果如下:
[de chin @ de chin-man jaro concurrent]$ python 3 current _ sleep . py-t17时间成本为:3.0313029289245605s这个结果也印证了我们之前的预期,因为16s的任务需要2s来执行,16s的任务结束后,需要等待1s剩余的任务完成。如果我们在这里不配置max_worker,我们会根据系统中最高的逻辑核心数将任务分配给多个进程。但在实际场景中,我们需要考虑很多因素的制约,比如内存的均衡分配,进程的数量(在大内存任务中,如果进程全开,可能会导致内存不足的问题)。只有满足所有的系统约束,才能发挥硬件的最佳性能。在下面的代码中,我们将给出一个如何配置执行任务的内核数量的方案:
# concurrent _ sleep . py import concurrent . futures import time import sysdef sleep(seconds):time . sleep(秒)if _ _ name _ _= _ _ main _ _ :if sys . argv[1]=-t :times=[1]* int(sys . argv[2])time 0=time . time()with concurrent . futures . processpool executor(max _ workers=4)As executor:executor . map(sleep,times) time1=time.time () print(时间开销为:{} s 。format (time1-time0))配置方法也很简单,就是在ProcessPoolExecutor函数的参数中引入max_worker。这里,我们首先将使用的最大内核数设置为4。
[de chin @ de chin-man jaro concurrent]$ python 3 concurrent _ sleep . py-t 16时间开销为:4.032958030700684s[de chin @ de chin-man jaro concurrent]$ python 3 current _ sleep . py-t17时间开销为:5.03267173614502s对于16s任务,启动了四核并行,因此任务在4s内完成。但是17s的任务也需要等1s,需要5s。
获取返回值。如果任务可以相互独立执行,不需要相互通信,自然是最理想的情况。但更多的时候,我们收集的是每个进程的返回值,通过这些我们可以互相交流。在并发的情况下,map函数的返回值直接是所有进程的返回值列表,更方便我们的任务执行。
# concurrent _ sleep . pyimport concurrent . futures import time import sysdef sleep(seconds):time . sleep(seconds)return seconds if _ _ name _ _= _ _ main _ _ :if sys . argv[1]=-t :times=[1]* int(sys . argv[2])time 0=time . time()with concurrent . futures . processpoolexecutor(max _ workers=4)as executor:results=executor . map(sleep,times) print(总睡眠cpu时间为:{}s 。format(sum(results)))time 1=time . time()print(时间成本为:{}s 。format(time1 - time0))在这个用例中,我们将map函数的结果存储到results参数中,最后对结果求和。在这个简单的例子中,返回的结果实际上是总的输入睡眠时间。执行结果如下:
[de chin @ de chin-man jaro concurrent]$ python 3 current _ sleep . py-t16总睡眠CPU时间为:16 st时间开销为:4.0342297852s可以看出成功获取了所有返回值。
总结多进程技术是一种独立于算法任务本身的优化技术。通过python中的并发库,可以轻松实现多进程任务,优化现有算法。这里我们也给出了一些多进程配置信息的参考方案,可以广泛应用于GPU和超级计算机相关领域。
版权声明本文首发链接为:https://www.cnblogs.com/dechinphy/p/concurrent.html.
作者:德钦菲
更多原创文章请参考:https://www.cnblogs.com/dechinphy/。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。