11

AI预测模型工程化性能调优 – 萌叔

 4 years ago
source link: http://vearne.cc/archives/39300?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc

最近经历了一次AI预测模型工程化性能调优,这里分享出来,希望对大家有所启发。

模型是keras训练的神经网络预测模型,输入一段文本,输出文本的分类结果。为了对外提供服务,已经将模型用 gunicorn + flask对模型进行封装,提供http接口。

  • OS:ubuntu 18.04
  • CPU:32核
  • 内存: 256GB
  • 显卡: Tesla P100
    前期的压测结果
wrk -t4 -c100 -d30s --script=post.lua --latency http://localhost:8080/api/predict
类型 CPU GPU
QPS 2.4 12.41

2. 观察性能指标

QPS过低不能满足业务方的要求,所以萌叔尝试对封装好的服务进行调优。
仔细观察了各项系统指标之后(cpu、load、磁盘IO、内存使用率、虚拟内存页换入换出)
萌叔发现了一个疑点。

2.1 keras 使用CPU

image_1e3kb21pu1lot1d0c9m4se01ccn9.png-221.8kB

在压测的过程中,CPU的使用率只能达到70%左右

2.2 keras 使用GPU

image_1e3kb32agbafjr11bh51ts1qlgm.png-127.9kB

在压测的过程中,GPU的使用率只能达到30%左右

神经网络模型对文本分类的预测过程,实际就是将输入文本转换成数值,再带入神经网络,进行的2次计算的过程。这是一个计算密集型的场景,性能瓶颈应该是CPU/GPU; 如果CPU、GPU没有打满,则说明性能仍有提升的空间。

3.1 初始协程模式

web使用Flask开发,启动脚本如下:

gunicorn -k gevent -t 300 -b 0.0.0.0:8080 run:app

gunicorn有几种工作模式

  • sync (进程模式)
  • eventlet
  • gevent (协程模式)
  • tornado
  • gthread

gevent是一种协程模式,它的特点是在请求的处理过程中有IO调用时(或者当前的协程主动让出CPU),会自动触发切换上下文切换,启动另一个协程,提高CPU的利用率。它特别适用于IO密集型的场景,尤其是对于处理过程中有对数据库的调用,第三方服务调用的情况。

然而本文的场景是模型运算过程,是计算密集型的场景,使用gevent可能并不合适。

3.2 尝试使用进程模式

gunicorn -w 5 -k sync -t 300 -b 0.0.0.0:8080 run:app
3.2.1 keras 使用CPU

image_1e3kdv5661ftbrfdfkh19kb1qat1t.png-32.4kB
在压测的过程中,CPU使用率95%

3.2.2 keras 使用GPU
WechatIMG14834.png-870.9kB

在压测的过程中,GPU使用率100%

可见性能已经达到了极限,优化结束。

使用gunicorn配置成进程模式后,启动时报”GPU out of memory”
此时可设置GPU显存动态装载,解决这个问题,详见参考资料2

import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.allow_growth = True  # dynamically grow the memory used on the GPU
config.log_device_placement = True  # to log device placement (on which device the operation ran)
                                    # (nothing gets printed in Jupyter, only if you run it standalone)
sess = tf.Session(config=config)
set_session(sess)  # set this TensorFlow session as the default session for Keras

最后让我们来对比一下,优化前和优化后的结果

类型 CPU GPU
优化前-QPS 2.4 12.41
优化后-QPS 3.36 42.19

可以看出QPS提升明显,尤其是使用GPU的情况。

正常情况gunicorn使用gevent,只能打满一个CPU核,为什么在当keras使用CPU时,多个CPU核的使用率都达到了70%左右。

萌叔的回答

当协程处理请求时,执行模型预测函数

model.predict()

predict函数原型

predict(x, batch_size=None, verbose=0, steps=None, callbacks=None, max_queue_size=10, workers=1, use_multiprocessing=False)

由协程创建了多进程,而这些进程其实都是不在gevent的控制范围内的

1.keras
2.Using allow_growth on keras with tensorflow
3.gunicorn-worker_class


请我喝瓶饮料

微信支付码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK