提升深度学习应用程序的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引入文本填充任务是很自然的。

  1. 首先,我们定义了文本填充任务的模型。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']

    注意:请首先下载经过预培训的伯特模型。

  2. 其次,利用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个请求。有关详细信息,请参见基准。

  3. 第三,通过服务拖缆封装模型函数。三行代码使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
    
  4. 最后,通过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上均匀分布。

  5. < > >

    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_streamer 
    
    0

    默认情况下,拖缆使用生成子进程运行GPU工作进程。拖缆使用进程间队列进行通信和排队。它可以将大量请求分发给多个工作人员进行处理。

    然后将模型的预测结果分批返回到相应的web服务器。结果被转发到相应的http响应。

    pip install service_streamer 
    
    1

    上面的方法很容易定义,但是主进程初始化模型占用了额外的内存。模型只能在同一个gpu上运行。 因此,我们提供了managedmodel类,以便在支持多个gpu的同时简化模型延迟初始化和迁移。

    pip install service_streamer 
    
    2

    分布式Web服务器

    一些cpu密集型的计算,如图像和文本预处理,需要首先在web服务器中完成。然后,预处理的数据被转发到gpu worker中进行预测。在实践中,cpu资源常常成为性能瓶颈。因此,我们还提供了多个Web服务器匹配(单个或多个)GPU工作线程的模式。

    使用redisstream为所有Web服务器和GPU工作程序指定唯一的redis地址。

    pip install service_streamer 
    
    3

    我们使用gunicornuwsgi来实现反向代理和负载平衡。

    pip install service_streamer 
    
    4

    每个请求将被负载均衡到每个Web服务器进行CPU预处理,然后均匀地分配到GPU Worker进行模型预测。

    未来的API

    如果您使用过任何并发库,您可能会熟悉future。 如果您想将服务拖缆用于排队请求或分布式GPU计算,并且使用的场景不是Web服务,则可以直接使用未来的API。

    pip install service_streamer 
    
    5

    基准

    基准

    我们利用wrk进行基准测试。

    测试示例和脚本可以在示例中找到。

    环境

    • GPU:Titan XP
    • CUDA:9.0
    • Pythorch:1.1

    单GPU过程

    αααα16 <表><广告>< T/> 天真的 拖缆 拖缆 重新流媒体 < /广告><正文> QPS12.78207.59321.70372.45延迟8440毫秒603.35毫秒392.66毫秒340.74毫秒

    多个GPU进程

    通过与单个web服务器进程的比较,验证了多gpu工作进程的通信和负载平衡机制的性能损失。

    我们采用gevent服务器是因为多线程flask服务器已经成为性能瓶颈。请参阅烧瓶/u multigpu example.py

    pip install service_streamer 
    
    7 <表><广告>GPU工人数 天真的 螺纹拖缆 拖缆 重新流媒体 < /广告><正文>11.62211.02362.69365.80 n/a n/a488.40609.63 n/a n/a494.201034.57
    • 线程拖缆由于python gil的限制,多个工作线程毫无意义。我们使用单个GPU工作人员进行比较研究。

    • 拖缆性能改善在大于2 GPU工作线程时不是线性的。 CPU利用率达到100。此时瓶颈是CPU,烧瓶的性能问题是障碍。

    利用未来的api启动多个gpu进程

    为了降低web服务器的性能影响,我们采用了未来api在本地进行多gpu benchmemark测试。请参阅future-example.py中的代码示例 <表><广告>GPU工人数 成批 螺纹拖缆 拖缆 重新流媒体 < /广告><正文>422.883401.01399.26384.79 n/a n/a742.16714.781 n/a n/a1400.121356.47

    可以看出,服务拖缆的性能几乎与gpu工作者的数量成线性关系。业务拖缆中进程间通信的效率比redis高。

    FAQ

    q:使用从allennlp培训的模型,设置allennlp的worker\u num=4,在推断过程中,16核CPU已满的原因是什么?速度比拖缆速度慢

    a:对于多进程推理,如果模型进程数据使用多线程的numpy,可能会导致cpu开销,导致多核计算速度慢于单核。使用第三方库(如alenlp、spacy等)时可能会出现这种问题。可以通过设置numpy threads环境变量来解决此问题。

    pip install service_streamer 
    
    8

    确保在导入numpy之前放置环境变量

    q:使用redisstreamer时,如果只有一个redis代理和多个模型,则输入批可能具有不同的结构。如何应对这种情况?

    a:在初始化工作流和拖缆时指定前缀,每个拖缆将使用一个唯一的频道。

    初始化工作者的示例:

    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

    欢迎加入QQ群-->: 979659372 Python中文网_新手群

    推荐PyPI第三方库


热门话题
添加组件后,java JTable为空   java将json发送到php并插入mysql,但返回null   java Spring引导JNDI CommonJ资源   从不同PC创建和合并后的Java servlet问题   java如何在使用findelements时从xpath获取文本   java使用spring boot使用gmail smtp发送电子邮件   java在不使用pojo、bean或getter和setter的情况下获取Json标题的Json数组   Java中的OpenFile对话框将null作为响应   JavaBuilder模式。扩展接口   java中无需替换的数据结构选取   java如何评价Encog中的预测神经网络   java如何在安卓中使用实际的HttpURLConnection进行单元测试?   java使用XML配置禁用WebSocket中的CSRF保护   java如何通过hibernate从多表查询中获取数据?   mysql如何在java中获取更新的行Id   java AEM/CQ组件单一组件/有限组件   java FFmpeg Javacv延迟问题   显示整数数组的java不起作用