控制Python线程的调度优先级?

36
我编写了一个脚本,使用两个线程池,每个线程池有十个线程,从API中提取数据。该线程池实现了ActiveState上的代码。每个线程池通过PubSub监视Redis数据库的新条目。当发布新条目时,Python将数据传递给一个函数,该函数使用Python的Subprocess.POpen执行PHP shell,以实际调用API。
这种启动PHP Shell的系统对于我的PHP Web应用程序的功能是必要的,因此无法避免使用Python启动PHP Shell。
此脚本仅在Linux服务器上运行。 我如何控制应用程序线程的niceness(调度优先级)? 编辑: 似乎在Python中控制单个线程的调度优先级是不可能的。是否有一种Python解决方案,或者至少有一个UNIX命令可以与我的脚本一起运行来控制优先级?
编辑2: 好吧,最终我没有找到一种处理这个问题的Python方式。现在我只是使用nice命令来运行我的脚本,就像这样:
nice -n 19 python MyScript.py
5个回答

33

由于在Python中线程使用全局解释器锁(GIL)实现,因此我认为无法控制线程优先级。即使你可以提高某个线程的CPU处理优先级,Python实现负责传递GIL时也不会意识到这一点。如果您能够在池中的单个线程中增加niceness(比如它正在执行更重要的任务),则需要使用自己的锁实现,以使较高优先级的线程更频繁地访问GIL。

通过谷歌搜索,我发现这篇文章与您所问的问题类似

说明为什么不起作用: http://www.velocityreviews.com/forums/t329441-threading-priority.html

说明我所建议的解决方法: http://bytes.com/topic/python/answers/645966-setting-thread-priorities


谢谢你的回答!我已经重新表述了问题,现在询问如何设置应用程序整体的调度优先级,而不是单个的。这应该仍然能够满足我的需求。我已经为你的回答点赞,并且如果没有其他回复的话,我会选择你作为最佳答案。 - backus

10
Python的线程文档明确提到不支持设置线程优先级:
引用自文档: “该模块的设计基于Java的线程模型。然而,Java将锁和条件变量作为每个对象的基本行为,而在Python中,它们是独立的对象。Python的Thread类仅支持Java的Thread类的行为子集;目前没有优先级、线程组,线程不能被销毁、停止、暂停、恢复或中断。当实现Java的Thread类的静态方法时,会将其映射到模块级别的函数。”

8

这个方法并不起作用,但是我试过了:

  1. 获取父进程的PID和优先级
  2. 使用concurrent.futures.ThreadPoolExecutor启动线程
  3. 在线程中使用ctypes获取(Linux)线程ID(可行)
  4. 使用os.setpriority(os.PRIO_PROCESS,tid,parent_priority+1)设置tid的优先级
  5. 从父进程中调用pool.shutdown()。

即使大量使用os.sched_yield(),子线程也永远不会在setpriority()之后真正运行。

通过阅读man手册,似乎线程没有改变(甚至自己的)调度优先级的能力;你必须对“capabilities”进行某些操作,以给线程赋予“CAP_SYS_NICE”的能力。即使以root权限运行进程也没有帮助;子线程仍然无法运行。


5

我知道已经过去了很久,但是最近我遇到了这个问题,我认为增加另一种选择可能会有用。

看看threading2,它是默认线程模块的一个即插即用替代和扩展,支持优先级和亲和力。


3
现在这个项目已经无人维护了,有一个链接指向https://rfk.id.au/blog/entry/archiving-open-source-projects/ :( - Andre Miras

0

我在想, 另一个相关问题的这个答案 是否在这种情况下有用呢?(链接)

由于您已经在使用 Subprocess.POpen 来启动 PHP 脚本,因此我认为您可以使用 "preexec_fn" 和预定义函数或 lambda 函数 (如上面链接的答案所示) 来设置每个启动的 PHP 线程的好级别。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接