• 模拟并发任务,观察多进程和多线程的cpu使用率(以及进程池的chunksize参数)


    1. 多进程 vs 多线程
    import threading
    import concurrent.futures
    
    def kai(n):
        while True:
            if n != 0:
                n+=1
        print(n)
    
    
    #ex = concurrent.futures.ThreadPoolExecutor(max_workers=5)  # 用线程
    ex = concurrent.futures.ProcessPoolExecutor(max_workers=5)  # 用进程
    
    ex_feature = ex.map(kai,[1,2,3,4,5])
    
    print(ex_feature)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    上述脚本可以验证对于纯计算类场景,对进程和多线程的效率差别(其实是对于cpu的充分使用程度)。

    但是并不是说多进程有多鸡肋,在IO密集的场景下:多线程在遇到IO等待时会释放GIL锁让其他线程有执行机会,还是可以充分提升任务执行效率的。而且多线程较多进程更为轻量,更适合IO密集场景下高并发量的并行处理场景。


    2. 验证excutor.map()中的chunksize参数的效果

    对0-100000之间能被3整除的数进行过滤,4个子进程

    import concurrent.futures
    
    def li(n):
        if n % 3 == 0:
            return n
    
    data=range(100000)
    ex = concurrent.futures.ProcessPoolExecutor(max_workers=4)
    #ex_feature = ex.map(li,data,chunksize=25000)
    ex_feature = ex.map(li,data)
    
    #print(ex_feature)
    
    #with open('/tmp/result_with_chunk', 'w') as f:  #用chunksize时的结果文件
    with open('/tmp/result_no_chunk', 'w') as f:     #不用chunksize时的结果文件
        for i in ex_feature:
            if i:
                f.write('{} '.format(i))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    然后通过系统time命令观察耗时

    ~]# time python3 /tmp/tt.py     #no chunksize
    
    real    0m18.694s
    user    0m26.665s
    sys     0m4.836s
    
    ~]# time python3 /tmp/tt.py     #with chunksize
    
    real    0m0.227s
    user    0m0.288s
    sys     0m0.055s
    
    对比结果文件,完全一致
    ~]# diff /tmp/result_with_chunk /tmp/result_no_chunk 
    ~]#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    可以看到,在用或不用chunksize参数时,两者效率简直无法相比

    待深入:chunksize的合理性(依据工作进程数,待处理数据总数等因素)


    3 两种进程池写法
    1. concurrent.futures.ProcessPoolExecutor()
    2. multiprocessing.pool.Pool()
    # test1方式1
    from multiprocessing import Pool
    
    def li(n):
        if n % 3 == 0:
            return n
    
    data=range(10000000)
    with Pool(5) as p:
        p.map(li,data,chunksize=2000000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    # test2方式2
    import concurrent.futures
    
    def li(n):
        if n % 3 == 0:
            return n
    
    data=range(10000000)
    ex = concurrent.futures.ProcessPoolExecutor(max_workers=4)
    ex.map(li,data,chunksize=2500000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    执行结果(各执行3次)

     ~]$ time python3 /tmp/test1
    
    real    0m1.582s
    user    0m2.786s
    sys     0m0.709s
     ~]$ time python3 /tmp/test1
    
    real    0m1.627s
    user    0m2.779s
    sys     0m0.717s
     ~]$ time python3 /tmp/test1
    
    real    0m1.583s
    user    0m2.776s
    sys     0m0.711s
     ~]$ time python3 /tmp/test2
    
    real    0m8.056s
    user    0m10.067s
    sys     0m1.783s
     ~]$ time python3 /tmp/test2
    
    real    0m7.961s
    user    0m10.094s
    sys     0m1.736s
     ~]$ time python3 /tmp/test2
    
    real    0m7.981s
    user    0m10.090s
    sys     0m1.671s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    看到方式1比方式2效率要高几倍

  • 相关阅读:
    Python 变量的定义和数据类型的转换
    基于JAVA线上动漫周边商城计算机毕业设计源码+数据库+lw文档+系统+部署
    C++DAY39
    Nginx 文件解析漏洞复现
    国产芯片ZT1826亮相IOTE展 以物联网技术助力行业数字化转型
    简历项目优化关键方法论-START
    小张的秋招面经(持续更新版)
    数据结构——树
    利用Hugging Face中的模型进行句子相似性实践
    Chromium 开发指南2024 Mac篇-安装和配置depot_tools工具(三)
  • 原文地址:https://blog.csdn.net/kai404/article/details/127615008