fastapi 收到一个 http 请求后,就创建一个新的 Thread,去执行一个机器学习模型代码,这块代码是我不懂也不可控的。我想知道有没有办法,可以控制杀死这个线程及所有相关的线程。

2021-10-31 22:41:11 +08:00
 zxCoder

这个模型代码单独运行时,如果我按 ctlr+C 停止的话,都很难直接停下来,里头好像有用到多线程啥的,反正太深层了看不懂。

以至于套到 fastapi 上之后,如果已经触发在跑这个模型了,我直接关掉 fastapi 程序也很难,ctlr+C 通常是关不了,只能直接 kill 。

有没有什么好一点的方法呢,可以让这个正在跑的 Thread 不管三七二十一,就给停下来,删掉。

2725 次点击
所在节点    Python
10 条回复
leimao
2021-10-31 22:53:12 +08:00
Kill thread 很难,似乎很少有办法。Kill process 可以,只要知道 PID 就行了。可以尝试一下和下面 Kill distributed training 类似的思路。
https://leimao.github.io/blog/Kill-PyTorch-Distributed-Training-Processes/
ipwx
2021-10-31 22:58:30 +08:00
对,用 多进程,直接 os.kill
feiandxs
2021-10-31 22:59:16 +08:00
fastapi 跑一个 api ,作为触发没问题,但我不建议直接在 fastapi 里调用。 是我的话我宁愿接个 celery 或者更简单的做个实现,来告知有个任务,然后由别的运行服务来进行对模型的调用。

并且对这样的模型的调用我也不觉得直接调用好,应该关进一个笼子里,笼子本身对资源占用,对进程管理做更好的管控。 其实我看你也就是想要这样的东西。

有个想法,其实可以用 py 来调 shell ,shell 来干这个杀的事。。。
ClericPy
2021-10-31 23:07:51 +08:00
接 celery 就太多不可控的东西了...

python 和多数语言一样线程是系统那边原生的, 很难杀死, 如果不嫌麻烦就丢到 Serverless 上?

嫌麻烦的话, 如果 fastapi 启动线程也用的 run_in_executor 那个, 用的时候用多进程那个 ProcessExecutor 就可以杀了(不过没试过 cancel 掉的时候会不会杀掉, 一般 INTSIG 会一路传递过去), 一般状态切换不频繁的多进程实际没多大开销, 应该能满足你.
niubee1
2021-11-01 00:33:35 +08:00
你只有用多进程,线程的话因为 GIL ,不适用于 CPU 密集的环境
abersheeran
2021-11-01 09:06:53 +08:00
你用 async def 就不会新开一个线程了,反正你跑的是机器学习代码,全是硬核运算,没必要开线程池。这个隐式转换真的是不咋地的设计。
locoz
2021-11-01 09:07:50 +08:00
简单点可以直接跑个容器,需要停的时候直接杀容器,里面再怎么样也得停…
wwqgtxx
2021-11-01 09:49:53 +08:00
如果有系统权限的话,试试 cgroups 相关的工具,比如 systemd-run 或者干脆上 docker 容器,这样能杀的比较干净
ospider
2021-11-01 09:57:15 +08:00
你这题目就错得离谱,不知道下边一群人答得什么劲……我没记错的话,FastAPI 用的是 ThreadPoolExecutor ,每次请求都开一个线程那开销得多大啊?

看看 FastAPI 自带的 BackgroundTasks 可不可以,或者试试用 gunicorn 部署。
leimao
2021-11-03 07:18:44 +08:00
@ospider 楼主表达问题给人的感觉就是 fastapi 是一个机器学习框架。机器学习不建议使用 Python 的多线程。这个不能怪我们这些不懂 fastapi 的人。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/811955

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX