控制子进程的 cpu 使用率 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
firejoke
V2EX    Python

控制子进程的 cpu 使用率

  •  
  •   firejoke 2022-01-19 23:37:07 +08:00 4003 次点击
    这是一个创建于 1411 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想到一个控制子进程的 cpu 使用率的简单方法。

    import platform import time from multiprocessing import Process, JoinableQueue import psutil from settings import CPU_FREQ, MIN_SLEEP_TIME_OF_SUBPROCESS, testLog # CPU_FREQ = psutil.cpu_freq().max * pow(10, 9) # MIN_SLEEP_TIME_OF_SUBPROCESS = 1 / CPU_FREQ def subp(queue: JoinableQueue): while 1: if queue.empty(): _st = 0 else: _st = queue.get() queue.task_done() time.sleep(_st) if __name__ == '__main__': sysv = platform.system().lower() expect = 90 queue = JoinableQueue() queue.put(MIN_SLEEP_TIME_OF_SUBPROCESS) sp = Process(target=subp, args=(queue,)) sp.start() spi = psutil.Process(sp.pid) if sysv == "windows": spi.nice(psutil.HIGH_PRIORITY_CLASS) else: spi.nice(28) if sysv != "windows": spi.ionice(psutil.IOPRIO_CLASS_RT, value=7) testLog.info(f"pid: {spi.pid}, ppid: {spi.ppid()}") time.sleep(5) while 1: scpu = spi.cpu_percent(MIN_SLEEP_TIME_OF_SUBPROCESS) if scpu >= expect: testLog.info(f"sub-process cpu: {scpu}") if sysv != "windows": testLog.info(f"sub-process cpu_num: {spi.cpu_num()}") st = 1 / (((scpu - expect) / 100) * CPU_FREQ) testLog.info(f"st: {st}") else: # st = MIN_SLEEP_TIME_OF_SUBPROCESS st = 0 queue.put(st) 

    原理如下:
    if 子进程的 cpu 占用率 > 预期:
    1 / ((当前的占用率- 预期)/ 满载值 * cpu 频率。)
    这个值就是子进程需要休眠的时间。
    子进程只使用单核时,满载值就是 100 ,子进程再开孙子进程的情况还没考虑。
    实测能达到预想效果。
    各位还有其他的方案可以借鉴下吗?

    14 条回复    2022-01-24 21:55:23 +08:00
    wevsty
        1
    wevsty  
       2022-01-19 23:41:20 +08:00
    windows 下面直接设置 job 就可以限制 cpu 使用了。
    junnplus
        2
    junnplus  
       2022-01-19 23:53:01 +08:00
    cgroups 不行么
    Buges
        3
    Buges  
       2022-01-19 23:57:01 +08:00 via Android
    win 不清楚,Linux 下直接 cgroup
    ClericPy
        4
    ClericPy  
       2022-01-20 00:00:19 +08:00
    cgroups 基本版本答案一样地在各种环境里存在

    虽然我平时用 nice 设置个低优先级就够使了, 但是我把内核占满时间一长会被 kill 不知道咋回事, 所以似乎也需要限制一下 cpu 了(否则就得 sleep 一会了)
    firejoke
        5
    firejoke  
    OP
       2022-01-20 09:32:13 +08:00
    @wevsty #1
    @junnplus #2
    @Buges #3
    @ClericPy #4
    我需要应用的场景,是在资源空闲的时候,用尽预期的所有资源,而在有其他进程也需要占用资源时,能动态的让出资源。
    也可以用 cgroups 设定进程组占用 cpu 时间比其他进程组要少,但这样我就得为每一个可能启用的其他任务规划资源占比,并且每次都要手动修改已有的 cgroup 参数。
    所以就想着,如果能自动动态的在程序成面规划资源占用的话,就能少动手了
    wevsty
        6
    wevsty  
       2022-01-20 09:37:40 +08:00
    @firejoke
    只是为了系统空闲的时候能使用 CPU 资源,忙的时候不要占用的话,Windows 下面直接设置进程优先级就行了。

    设置进程优先级为最低,这样 Windows 会尽可能的调度其他进程,只有空闲的时候才会把 CPU 时间交给低优先级进程。
    ClericPy
        7
    ClericPy  
       2022-01-20 10:13:29 +08:00
    @firejoke

    我也是这个场景啊, 所以我用的 nice 把优先级调低凑合用着, 实际效果没发现多好, 想做自动伸缩资源占用的场景很多, 比如 Hadoop 上想用空闲资源计算不重要的离线, 那里提供的优先级队列在队列已经启动的时候依然没法让出 CPU 来...

    同关注一下看看有没有更好方案
    firejoke
        8
    firejoke  
    OP
       2022-01-20 10:38:14 +08:00
    @wevsty #6
    在系统成面设置进程优先级来控制资源调度确实要方便很多,但就像 @ClericPy #7 描述的,操作系统内的资源调度对我们来说约等于是黑盒,不能达到想要的效果,所以如果能在程序成面做到控制的话,可控度就高多了,希望能找到更合适的方案。
    2i2Re2PLMaDnghL
        9
    2i2Re2PLMaDnghL  
       2022-01-20 11:02:02 +08:00
    @ClericPy dmesg 看下 kill 的原因? nice 值好像会影响到 OOM kill 的顺序。
    (不如用竞价实例(误
    wevsty
        10
    wevsty  
       2022-01-20 11:33:47 +08:00
    @firejoke
    常见的系统内核都被人研究的比较透彻了,所以这些内核提供的资源调度方式都是比较好预期的。

    以调度的眼光来看,一个耗时任务所需要的 CPU 时间是无穷大的(因为无法预知具体需要多少时间来完成任务),而 CPU 时间显然是有限的。
    对 Windows 来说,Windows 会优先保证在调度周期内每个线程都能得到一定时间的执行的机会,在此基础上,剩余的时间按照优先级分配给各个线程。也就是说,进程优先级实际上保证的也是任务在系统中所占用的时间比例。
    我不知道所谓低优先级任务启动时不能让出 CPU 时间是一个什么概念,但是我十分确定,在高优先级线程需要 CPU 时间时,对比低优先级线程高优先级线程会获得更多的 CPU 时间。
    在 Windows 中,还可以给进程设置 JOBOBJECT_CPU_RATE_CONTROL_INFORMATION ,可以设定 JOB 中进程使用的 CPU 占比或者时间,可以设定为动态比值,也可以设定绝对周期。这样可以比较好的控制 CPU 时间的分配。

    最后资源调度本来就是内核的活,用户态根本拿不到准确的数据来进行调度。
    如果内核提供的优先级+CPU 时间限制还满足不了你的需求,那你可能需要的是自己定制一个系统内核。
    ClericPy
        11
    ClericPy  
       2022-01-20 12:42:54 +08:00
    @2i2Re2PLMaDnghL
    问题就是不是 OOM Kill 的, python 里多进程里每个进程高并发协程跑满 CPU, 内存只用了 200 多 MB, 任务主要就是流式下载图片并流式上传到 S3... 连个 SIGABRT 都没发, 看 journal 也没看出啥东西

    过段时间看看整 Serverless 上了, 竞价实例早就想用了, 但是运维跑路了申请不下来
    firejoke
        12
    firejoke  
    OP
       2022-01-20 17:41:36 +08:00
    @wevsty #10 我晚上回去试试,不过 psutil 库只能设置指定进程的优先级,在 Windows 是用 SetPriorityClass 实现的,只有几个固定优先级和后台模式。
    firejoke
        13
    firejoke  
    OP
       2022-01-20 20:25:32 +08:00
    @wevsty #10 在 Windows 上测了。

    测试环境:
    测试中把所有进程包括子进程都调整到同一 cpu 核上;
    运行中通过任务管理器确认了程序内设置的优先级是生效的;
    子进程用 multiprocessing.Process 生成的,在 Windows 上是 spawn 模式,会启动一个全新的解释器运行子进程。

    测试结果:
    两个独立进程之间,可以通过设置优先级,让优先级高的占用更多 cpu 时间,而相同优先级的会竞争。
    同一父进程的两个子进程之间,优先级没起到作用;
    不同父进程的两个子进程之间,不论是设置父进程的优先级还是子进程的优先级或者全都配置,两个子进程仍然会竞争。
    woodpenker
        14
    woodpenker  
       2022-01-24 21:55:23 +08:00
    kill STOP/CONT + sleep 就搞定了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5752 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 43ms UTC 02:08 PVG 10:08 LAX 18:08 JFK 21:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86