提升深度学习应用程序的web服务
service-streamer的Python项目详细描述
服务拖缆
提升您的深度学习应用程序的web服务。 自述
什么是服务拖缆-" rel="nofollow">什么是服务拖缆?突出显示•。 安装. 在5分钟内开发bert服务• api•。 基准. 常见问题解答•
< H6> •Shannani制造•:Globe_with_Meridians:http://www.shannani.com/什么是业务拖缆?
小批量收集数据样本,通常用于深度学习模型。这样,模型就可以利用gpu的并行计算能力。然而,用户对web服务的请求通常是离散的。如果使用传统的循环服务器或线程服务器,gpu将空闲处理一次一个请求。当有并发用户请求时,延迟时间将线性增加。
Servicestreamer是一个用于机器学习应用程序的Web服务的中间件。用户的队列请求被抽样成小批量。ServiceStreamer可以通过提高GPU利用率显著提高系统的总体性能。
亮点
- :孵化小鸡:易于使用:微小的改变可以使模型加速10倍。
- :zap:快速处理速度:机器学习模型在线推理的低延迟。
- :octopus:良好的可扩展性:易于应用于多GPU场景以处理大量请求。
- :交叉剑:适用性:与任何web框架和/或深度学习框架一起使用。
安装
使用pip
安装servicestream,需要python>;=3.5:
pip install service_streamer
在5分钟内开发BERT服务
我们提供一个循序渐进的教程,让您在5分钟内将bert联机。该服务每秒处理1400个句子。
文本填充
是自然语言处理中的一项任务:给定一个随机删除多个单词的句子,该模型通过给定的上下文预测那些删除的单词。
bert
在这两年中引起了广泛的关注,它在许多nlp任务中取得了最新的成果。伯特利用"蒙面语言模型(mlm)"作为训练前的目标之一。传销模型从输入中随机屏蔽一些令牌,其目的是基于上下文预测被屏蔽词的原始词汇id。传销与文字填充有相似之处。将bert引入文本填充任务是很自然的。
首先,我们定义了文本填充任务的模型。
predict
函数接受一批语句并返回[mask]
标记的预测位置结果。classTextInfillingModel(object):...batch=["twinkle twinkle [MASK] star.","Happy birthday to [MASK].",'the answer to life, the [MASK], and everything.']model=TextInfillingModel()outputs=model.predict(batch)print(outputs)# ['little', 'you', 'universe']
注意:请首先下载经过预培训的伯特模型。
其次,利用flask将预测接口打包到web服务。烧瓶示例.py
model=TextInfillingModel()@app.route("/naive",methods=["GET","POST"])defnaive_predict():ifrequest.method=="GET":inputs=request.args.getlist("s")else:inputs=request.form.getlist("s")outputs=model.predict(inputs)returnjsonify(outputs)app.run(port=5005)
请运行low">烧瓶示例.py,然后您将得到一个普通的Web服务器。
curl -X POST http://localhost:5005/naive -d 's=Happy birthday to [MASK].'["you"]
此时,web服务器每秒只能处理12个请求。有关详细信息,请参见基准。
第三,通过
服务拖缆
封装模型函数。三行代码使bert服务的预测速度达到每秒200多句(快16倍)。fromservice_streamerimportThreadedStreamerstreamer=ThreadedStreamer(model.predict,batch_size=64,max_latency=0.1)@app.route("/stream",methods=["POST"])defstream_predict():inputs=request.form.getlist("s")outputs=streamer.predict(inputs)returnjsonify(outputs)app.run(port=5005,debug=False)
运行flask example.py并用wrk测试性能。
./wrk -t 2 -c 128 -d 20s --timeout=10s -s example/benchmark.lua http://127.0.0.1:5005/stream ... Requests/sec: 200.31
最后,通过
streamer
封装模型,并在多个gpu上启动服务工作者。拖缆
进一步加快推理速度,并达到每秒1000多句(快80倍)。fromservice_streamerimportManagedModel,StreamerclassManagedBertModel(ManagedModel):definit_model(self):self.model=TextInfillingModel()defpredict(self,batch):returnself.model.predict(batch)streamer=Streamer(ManagedBertModel,batch_size=64,max_latency=0.1,worker_num=8,cuda_devices=(0,1,2,3))app.run(port=5005,debug=False)
可启动8个GPU工作程序,并在4个GPU上均匀分布。
< > >- GPU:Titan XP
- CUDA:9.0
- Pythorch:1.1
线程拖缆
由于python gil的限制,多个工作线程毫无意义。我们使用单个GPU工作人员进行比较研究。拖缆
性能改善在大于2 GPU工作线程时不是线性的。 CPU利用率达到100。此时瓶颈是CPU,烧瓶的性能问题是障碍。
API
快速启动
一般来说,通过使用并行计算,推理速度会更快。
outputs=model.predict(batch_inputs)
Servicestreamer是用于机器学习应用程序的Web服务的中间件。来自用户的队列请求被安排成小批量并转发到GPU工作进程。ServiceStreamer牺牲了一定的延迟(默认最大值为0.1s),并通过提高GPU利用率来提高整体性能。
fromservice_streamerimportThreadedStreamer# Encapsulate batch_predict function with Streamerstreamer=ThreadedStreamer(model.predict,batch_size=64,max_latency=0.1)# Replace model.predict with streamer.predictoutputs=streamer.predict(batch_inputs)
在多线程(或协调)上启动Web服务器。通过添加几行代码,您的服务器通常可以实现10倍的速度(批处理大小/批处理每个请求的速度
)。
分布式GPU工作程序
在实际应用中,web服务器(qps)的性能远远高于gpu模型。我们还支持一个带有多个GPU工作进程的Web服务器。
pip install service_streamer0
默认情况下,拖缆
使用生成
子进程运行GPU工作进程。拖缆
使用进程间队列进行通信和排队。它可以将大量请求分发给多个工作人员进行处理。
然后将模型的预测结果分批返回到相应的web服务器。结果被转发到相应的http响应。
pip install service_streamer1
上面的方法很容易定义,但是主进程初始化模型占用了额外的内存。模型只能在同一个gpu上运行。
因此,我们提供了managedmodel
类,以便在支持多个gpu的同时简化模型延迟初始化和迁移。
pip install service_streamer2
分布式Web服务器
一些cpu密集型的计算,如图像和文本预处理,需要首先在web服务器中完成。然后,预处理的数据被转发到gpu worker中进行预测。在实践中,cpu资源常常成为性能瓶颈。因此,我们还提供了多个Web服务器匹配(单个或多个)GPU工作线程的模式。
使用redisstream
为所有Web服务器和GPU工作程序指定唯一的redis地址。
pip install service_streamer3
我们使用gunicorn
或uwsgi
来实现反向代理和负载平衡。
pip install service_streamer4
每个请求将被负载均衡到每个Web服务器进行CPU预处理,然后均匀地分配到GPU Worker进行模型预测。
未来的API
如果您使用过任何并发库,您可能会熟悉future
。
如果您想将服务拖缆用于排队请求或分布式GPU计算,并且使用的场景不是Web服务,则可以直接使用未来的API。
pip install service_streamer5
基准
基准
我们利用wrk进行基准测试。
测试示例和脚本可以在示例中找到。
环境
单GPU过程
αααα16 <表><广告>多个GPU进程
通过与单个web服务器进程的比较,验证了多gpu工作进程的通信和负载平衡机制的性能损失。
我们采用gevent服务器是因为多线程flask服务器已经成为性能瓶颈。请参阅烧瓶/u multigpu example.py
pip install service_streamer7 <表><广告>
利用未来的api启动多个gpu进程
为了降低web服务器的性能影响,我们采用了未来api在本地进行多gpu benchmemark测试。请参阅future-example.py中的代码示例
<表><广告> 可以看出, q:使用从allennlp培训的模型,设置allennlp的 a:对于多进程推理,如果模型进程数据使用多线程的numpy,可能会导致cpu开销,导致多核计算速度慢于单核。使用第三方库(如alenlp、spacy等)时可能会出现这种问题。可以通过设置 确保在导入numpy之前放置环境变量 q:使用redisstreamer时,如果只有一个redis代理和多个模型,则输入批可能具有不同的结构。如何应对这种情况? a:在初始化工作流和拖缆时指定前缀,每个拖缆将使用一个唯一的频道。 初始化工作者的示例: 使用拖缆产生结果的示例: < /广告><正文>GPU工人数
成批
螺纹拖缆
拖缆
重新流媒体
422.883 401.01 399.26 384.79 n/a n/a 742.16 714.781 n/a n/a 1400.12 1356.47 服务拖缆的性能几乎与gpu工作者的数量成线性关系。
业务拖缆中进程间通信的效率比redis高。
FAQ
worker\u num=4
,在推断过程中,16核CPU已满的原因是什么?速度比拖缆速度慢numpy threads
环境变量来解决此问题。pip install service_streamer
8
pip install service_streamer
9
classTextInfillingModel(object):...batch=["twinkle twinkle [MASK] star.","Happy birthday to [MASK].",'the answer to life, the [MASK], and everything.']model=TextInfillingModel()outputs=model.predict(batch)print(outputs)# ['little', 'you', 'universe']
0
推荐PyPI第三方库