您当前的位置:首页 > 电脑百科 > 程序开发 > 算法

微信 NLP 算法微服务治理

时间:2023-05-04 13:34:57  来源:DataFunTalk  作者:

一、概述

马斯克收购了推特,但对其技术表示不满。认为主页速度过慢是因为有 1000 多个 RPC。先不评价马斯克所说的原因是否正确,但可以看出,互联网上为用户提供的一个完整的服务,背后会有大量的微服务调用。

 

图片

 

微信读书推荐为例,分为召回和排序两个阶段。

 

图片

 

请求到达后,会先从用户特征微服务拉取特征,把特征组合在一起进行特征筛选,然后调用召回相关的微服务,这一流程还需要乘以一个 N,因为我们是多路召回,会有很多类似的召回流程在同时运行。下面的是排序阶段,从多个特征微服务中拉取相关特征,组合后多次调用排序模型服务。获得最终结果后,一方面将最终结果返回给调用方,另一方面还要将流程的一些日志发送给日志系统留档。

读书推荐只是微信读书整个 App 中非常小的一部分,由此可见,即便是一个比较小的服务后面也会有大量的微服务调用。管中窥豹,可以意料到整个微信读书的系统会有巨量的微服务调用。

大量的微服务带来了什么问题?

 

图片

 

根据日常工作的总结,主要是有以上三方面的挑战:

① 管理方面:主要是围绕如何高效地管理、开发以及部署大量的算法微服务。

② 性能方面:要尽量提升微服务,特别是算法微服务的性能。

③ 调度方面:如何在多个同类算法微服务之间实现高效合理的负载均衡。

二、微服务所面临的管理问题

1、开发和部署:CI/CD 系统提供自动打包和部署

第一点是我们提供了一些自动打包和部署的流水线,减轻算法同学开发算法微服务的压力,现在算法同学只需要写一个 Python/ target=_blank class=infotextkey>Python 函数,流水线会自动拉取预先写好的一系列微服务模板,并将算法同学开发的函数填入,快速搭建微服务。

2、扩缩容:任务积压感知自动扩缩容

第二点是关于微服务的自动扩缩容,我们采取的是任务积压感知的方案。我们会主动去探测某一类任务积压或空闲的程度,当积压超过某一阈值后就会自动触发扩容操作;当空闲达到某一阈值后,也会去触发缩减微服务的进程数。

3、微服务组织:图灵完备 DAG / DSL / 自动压测 / 自动部署

第三点是如何把大量的微服务组织在一起,来构造出完整的上层服务。我们的上层服务是用 DAG 去表示的,DAG 的每一个节点代表一个对微服务的调用,每一条边代表服务间数据的传递。针对 DAG,还专门开发了 DSL(领域特定语言),更好地描述和构造 DAG。并且我们围绕 DSL 开发了一系列基于网页的工具,可以直接在浏览器里进行上层服务的可视化构建、压测和部署。

4、性能监控:Trace 系统

第四点性能监控,当上层服务出现问题时要去定位问题,我们构建了一套自己的 Trace 系统。针对每一个外来请求,都有一整套的追踪,可以查看请求在每一个微服务的耗时,从而发现系统的性能瓶颈。

三、微服务所面临的性能问题

一般来说,算法的性能耗时都在深度学习模型上,优化算法微服务的性能很大一部分着力点就在优化深度学习模型 infer 性能。可以选择专用的 infer 框架,或尝试深度学习编译器,Kernel 优化等等方法,对于这些方案,我们认为并不是完全有必要。在很多情况下,我们直接用 Python 脚本上线,一样可以达到比肩 C++ 的性能。

不是完全有必要的原因在于,这些方案确实能带来比较好的性能,但是性能好不是服务唯一的要求。有一个很著名的二八定律,以人与资源来描述,就是 20% 的人会产生 80% 的资源,换句话说,20% 的人会提供 80% 的贡献。对于微服务来说,也是适用的。

我们可以把微服务分为两类,首先,成熟稳定的服务,数量不多,可能只占有 20%,但是承担了 80% 的流量。另一类是一些实验性的或者还在开发迭代中的服务,数量很多,占了 80%,但是承担的流量却只占用的 20%,很重要的一点是,经常会有变更和迭代,因此对快速开发和上线也会有比较强的需求。

前面提到的方法,比如 Infer 框架,Kernel 优化等,不可避免的需要额外消耗开发成本。成熟稳定的服务还是很适合这类方法,因为变更比较少,做一次优化能持续使用很久。另一方面,这些服务承担的流量很大,可能一点点的性能提升,就能带来巨大的影响,所以值得去投入成本。

但这些方法对于实验性服务就不那么合适了,因为实验性服务会频繁更新,我们无法对每一个新模型都去做新的优化。针对实验性服务,我们针对 GPU 混合部署场景,自研了 Python 解释器 —— PyInter。实现了不用修改任何代码,直接用 Python 脚本上线,同时可以获得接近甚至超过 C++ 的性能。

 

图片

 

我们以 Huggingface 的 bert-base 为标准,上图的横轴是并发进程数,表示我们部署的模型副本的数量,可以看出我们的 PyInter 在模型副本数较多的情况下 QPS 甚至超越了 onnxruntime。

 

图片

 

通过上图,可以看到 PyInter 在模型副本数较多的情况下相对于多进程和 ONNXRuntime 降低了差不多 80% 的显存占用,而且大家注意,不管模型的副本数是多少,PyInter 的显存占用数是维持不变的。

我们回到之前比较基础的问题:Python 真的慢吗?

没错,Python 是真的慢,但是 Python 做科学计算并不慢,因为真正做计算的地方并非 Python,而是调用 MKL 或者 cuBLAS 这种专用的计算库。

那么 Python 的性能瓶颈主要在哪呢?主要在于多线程下的 GIL(Global Interpreter Lock),导致多线程下同一时间只能有一个线程处于工作状态。这种形式的多线程对于 IO 密集型任务可能是有帮助的,但对于模型部署这种计算密集型的任务来说是毫无意义的。

 

图片

 

那是不是换成多进程,就能解决问题呢?

 

图片

 

其实不是,多进程确实可以解决 GIL 的问题,但也会带来其它新的问题。首先,多进程之间很难共享 CUDA Context/model,会造成很大的显存浪费,这样的话,在一张显卡上部署不了几个模型。第二个是 GPU 的问题,GPU 在同一时间只能执行一个进程的任务,并且 GPU 在多个进程间频繁切换也会消耗时间。

对于 Python 场景下,比较理想的模式如下图所示:

 

图片

 

 

通过多线程部署,并且去掉 GIL 的影响,这也正是 PyInter 的主要设计思路,将多个模型的副本放到多个线程中去执行,同时为每个 Python 任务创建一个单独的互相隔离的 Python 解释器,这样多个任务的 GIL 就不会互相干扰了。这样做集合了多进程和多线程的优点,一方面 GIL 互相独立,另一方面本质上还是单进程多线程的模式,所以显存对象可以共享,也不存在 GPU 的进程切换开销。

PyInter 实现的关键是进程内动态库的隔离,解释器的隔离,本质上是动态库的隔离,这里自研了动态库加载器,类似 dlopen,但支持“隔离”和“共享”两种动态库加载方式。

 

图片

 

以“隔离”方式加载动态库,会把动态库加载到不同的虚拟空间,不同的虚拟空间互相之间看不到。以“共享”方式加载动态库,那么动态库可以在进程中任何地方看到和使用,包括各个虚拟空间内部。

以“隔离”方式加载 Python 解释器相关的库,再以“共享”方式加载 cuda 相关的库,这样就实现了在隔离解释器的同时共享显存资源。

四、微服务所面临的调度问题

多个微服务起到同等的重要程度以及同样的作用,那么如何在多个微服务之间实现动态的负载均衡。动态负载均衡很重要,但几乎不可能做到完美。

为什么动态负载均衡很重要?原因有以下几点:

(1)机器硬件差异(CPU / GPU);

(2)Request 长度差异(翻译 2 个字 / 翻译 200 个字);

(3)Random 负载均衡下,长尾效应明显:

① P99/P50 差异可达 10 倍;

② P999/P50 差异可达 20 倍。

(4)对微服务来说,长尾才是决定整体速度的关键。

处理一个请求的耗时,变化比较大,算力区别、请求长度等都会影响耗时。微服务数量增多,总会有一些微服务命中长尾部分,会影响整个系统的响应时间。

为什么动态负载均衡难以完美?

方案一:所有机器跑一遍 Benchmark。

这种方案不“动态”,无法应对 Request 长度的差异。并且也不存在一个完美的 Benchmark 能反应性能,对于不同模型来说不同机器的反应都会不同。

方案二:实时获取每一台机器的状态,把任务发给负载最轻的。

这一方案比较直观,但问题在于在分布式系统中没有真正的“实时”,信息从一台机器传递到另一台机器一定会花费时间,而在这一时间中,机器状态就可以发生了改变。比如在某一瞬间,某一台 Worker 机器是最空闲的,多台负责任务分发的 Master 机器都感知到了,于是都把任务分配给这台最空闲的 Worker,这台最空闲的 Worker 瞬间变成了最忙的,这就是负载均衡中著名的潮汐效应。

方案三:维护一个全局唯一的任务队列,所有负责任务分发的 Master 都把任务发送到队列中,所有 Worker 都从队列中取任务。

这一方案中,任务队列本身就可能成为一个单点瓶颈,难以横向扩展。

动态负载均衡难以完美的根本原因是信息的传递需要时间,当一个状态被观测到后,这个状态一定已经“过去”了。YouTube 上有一个视频,推荐给大家,“Load Balancing is Impossible” https://www.youtube.com/watch?v=kpvbOzHUakA。

关于动态负载均衡算法,Power of 2 Choices 算法是随机选择两个 worker,将任务分配给更空闲的那个。这个算法是我们目前使用的动态均衡算法的基础。但是 Power of 2 Choices 算法存在两大问题:首先,每次分配任务之前都需要去查询下 Worker 的空闲状态,多了一次 RTT;另外,有可能随机选择的两个 worker 刚好都很忙。为了解决这些问题,我们进行了改进。

 

图片

 

改进后的算法是 Joint-Idle-Queue。

 

图片

 

我们在 Master 机器上增加了两个部件,Idle-Queue 和 Amnesia。Idle-Queue 用来记录目前有哪些 Worker 处于空闲状态。Amnesia 记录在最近一段时间内有哪些 Worker 给自己发送过心跳包,如果某个 Worker 长期没有发送过心跳包,那么 Amnesia 就会逐渐将其遗忘掉。每一个 Worker 周期性上报自己是否空闲,空闲的 Worker 选择一个 Master 上报自己的 IdIeness,并且报告自己可以处理的数量。Worker 在选择 Master 时也是用到 Power of 2 Choices 算法,对其他的 Master,Worker 上报心跳包。

有新的任务到达时,Master 从 Idle-Queue 里随机 pick 两个,选择历史 latency 更低的。如果 Idle-Queue 是空的,就会去看 Amnesia。从 Amnesia 中随机 pick 两个,选择历史 latency 更低的。

在实际的效果上,采用该算法,可以把 P99/P50 压缩到 1.5 倍,相比 Random 算法有 10 倍的提升。

五、总结

在模型服务化的实践中,我们遇到了三个方面的挑战:

首先是对于大量的微服务,如何进行管理,如何优化开发、上线和部署的流程,我们的解决方案是尽量自动化,抽取重复流程,将其做成自动化流水线和程序。

第二是模型性能优化方面,如何让深度学习模型微服务运行得更加高效,我们的解决方案是从模型的实际需求出发,对于比较稳定、流量较大的服务进行定制化的优化,对于实验型的服务采用 PyInter,直接用 Python 脚本上线服务,也能达到 C++ 的性能。

第三是任务调度问题,如何实现动态负载均衡,我们的解决方案是在 Power of 2 Choices 的基础上,开发了 JIQ 算法,大幅缓解了服务耗时的长尾问题。



Tags:算法   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
诱导付费、自动扣费……微短剧被质疑借助算法精准“围猎”老年人
诱导付费、自动扣费、重复收费……聚焦身边的消费烦心事⑦丨一些微短剧被质疑借助算法精准“围猎”老年人中工网北京3月31日电(工人日报—中工网记者刘兵)...【详细内容】
2024-04-01  Search: 算法  点击:(6)  评论:(0)  加入收藏
分析网站SEO快速排名算法对网站具体的影响效果
亲爱的朋友们,今天我想和大家分享一个我们都关心的话题——网站SEO快速排名算法对网站我们身处一个信息爆炸的时代,如何在海量的信息中脱颖而出,成为了一个我们不得...【详细内容】
2024-03-28  Search: 算法  点击:(12)  评论:(0)  加入收藏
当prompt策略遇上分治算法,南加大、微软让大模型炼成「火眼金睛」
近年来,大语言模型(LLMs)由于其通用的问题处理能力而引起了大量的关注。现有研究表明,适当的提示设计(prompt enginerring),例如思维链(Chain-of-Thoughts),可以解锁 LLM 在不同领域的...【详细内容】
2024-03-12  Search: 算法  点击:(12)  评论:(0)  加入收藏
谷歌宣布更新搜索算法:打击AI生成内容,提高搜索结果质量
IT之家 3 月 6 日消息,谷歌于当地时间 5 日发文宣布,针对用户对搜索结果质量下降的反馈,将对算法进行调整,旨在打击 AI 生成的内容以及内容农场等垃圾信息,使用户能够看到更多“...【详细内容】
2024-03-06  Search: 算法  点击:(38)  评论:(0)  加入收藏
小红书、视频号、抖音流量算法解析,干货满满,值得一看!
咱们中国现在可不是一般的牛!网上的网友已经破了十个亿啦!到了这个互联网的新时代,谁有更多的人流量,谁就能赢得更多的掌声哦~抖音、小红书、、视频号,是很多品牌必争的流量洼地...【详细内容】
2024-02-23  Search: 算法  点击:(13)  评论:(0)  加入收藏
雪花算法详解与Java实现:分布式唯一ID生成原理
SnowFlake 算法,是 Twitter 开源的分布式 ID 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳...【详细内容】
2024-02-03  Search: 算法  点击:(50)  评论:(0)  加入收藏
简易百科之什么是搜索引擎的PageRank算法?
简易百科之什么是搜索引擎的PageRank算法?在互联网时代,搜索引擎是我们获取信息的重要工具。而PageRank算法则是搜索引擎的核心技术之一,它决定了网页在搜索结果中的排名。那么...【详细内容】
2024-01-24  Search: 算法  点击:(50)  评论:(0)  加入收藏
PageRank算法揭秘:搜索引擎背后的魔法师的工作原理
PageRank(PR)算法是由谷歌创始人之一的拉里·佩奇LarryPage命名的一种衡量网站页面重要性的方法。根据谷歌的说法,PageRank通过计算页面链接的数量和质量来粗略估计分...【详细内容】
2024-01-23  Search: 算法  点击:(44)  评论:(0)  加入收藏
程序开发中常用的十种算法,你用过几种?
当编写程序时,了解和使用不同的算法对解决问题至关重要。以下是C#中常用的10种算法,每个算法都伴随着示例代码和详细说明。1. 冒泡排序 (Bubble Sort):冒泡排序是一种简单的比...【详细内容】
2024-01-17  Search: 算法  点击:(44)  评论:(0)  加入收藏
百度最新的搜索引擎算法是什么样的?
百度搜索引擎算法是百度用来决定网页排名的算法。它是百度搜索技术的核心,也是百度作为全球最大的中文搜索引擎的基石。随着互联网的发展和用户需求的不断变化,百度搜索引擎算...【详细内容】
2024-01-10  Search: 算法  点击:(86)  评论:(0)  加入收藏
▌简易百科推荐
小红书、视频号、抖音流量算法解析,干货满满,值得一看!
咱们中国现在可不是一般的牛!网上的网友已经破了十个亿啦!到了这个互联网的新时代,谁有更多的人流量,谁就能赢得更多的掌声哦~抖音、小红书、、视频号,是很多品牌必争的流量洼地...【详细内容】
2024-02-23  二手车小胖说    Tags:流量算法   点击:(13)  评论:(0)  加入收藏
雪花算法详解与Java实现:分布式唯一ID生成原理
SnowFlake 算法,是 Twitter 开源的分布式 ID 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳...【详细内容】
2024-02-03   一安未来  微信公众号  Tags:雪花算法   点击:(50)  评论:(0)  加入收藏
程序开发中常用的十种算法,你用过几种?
当编写程序时,了解和使用不同的算法对解决问题至关重要。以下是C#中常用的10种算法,每个算法都伴随着示例代码和详细说明。1. 冒泡排序 (Bubble Sort):冒泡排序是一种简单的比...【详细内容】
2024-01-17  架构师老卢  今日头条  Tags:算法   点击:(44)  评论:(0)  加入收藏
百度推荐排序技术的思考与实践
本文将分享百度在推荐排序方面的思考与实践。在整个工业界的推广搜场景上,特征设计通常都是采用离散化的设计,需要保证两方面的效果,一方面是记忆,另一方面是泛化。特征都是通过...【详细内容】
2024-01-09  DataFunTalk  微信公众号  Tags:百度推荐   点击:(77)  评论:(0)  加入收藏
什么是布隆过滤器?如何实现布隆过滤器?
以下我们介绍了什么是布隆过滤器?它的使用场景和执行流程,以及在 Redis 中它的使用,那么问题来了,在日常开发中,也就是在 Java 开发中,我们又将如何操作布隆过滤器呢?布隆过滤器(Blo...【详细内容】
2024-01-05  Java中文社群  微信公众号  Tags:布隆过滤器   点击:(87)  评论:(0)  加入收藏
面向推荐系统的深度强化学习算法研究与应用
随着互联网的快速发展,推荐系统在各个领域中扮演着重要的角色。传统的推荐算法在面对大规模、复杂的数据时存在一定的局限性。为了解决这一问题,深度强化学习算法应运而生。本...【详细内容】
2024-01-04  数码小风向    Tags:算法   点击:(96)  评论:(0)  加入收藏
非负矩阵分解算法:从非负数据中提取主题、特征等信息
非负矩阵分解算法(Non-negativeMatrixFactorization,简称NMF)是一种常用的数据分析和特征提取方法,主要用于从非负数据中提取主题、特征等有意义的信息。本文将介绍非负矩阵分解...【详细内容】
2024-01-02  毛晓峰    Tags:算法   点击:(63)  评论:(0)  加入收藏
再谈前端算法,你这回明白了吗?
楔子 -- 青蛙跳台阶一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶,求该青蛙跳上一个n级的台阶总共需要多少种跳法。分析: 当n=1的时候,①只需要跳一次即可;只有一种跳法,即f(...【详细内容】
2023-12-28  前端爱好者  微信公众号  Tags:前端算法   点击:(108)  评论:(0)  加入收藏
三分钟学习二分查找
二分查找是一种在有序数组中查找元素的算法,通过不断将搜索区域分成两半来实现。你可能在日常生活中已经不知不觉地使用了大脑里的二分查找。最常见的例子是在字典中查找一个...【详细内容】
2023-12-22  小技术君  微信公众号  Tags:二分查找   点击:(78)  评论:(0)  加入收藏
强化学习算法在资源调度与优化中的应用
随着云计算和大数据技术的快速发展,资源调度与优化成为了现代计算系统中的重要问题。传统的资源调度算法往往基于静态规则或启发式方法,无法适应动态变化的环境和复杂的任务需...【详细内容】
2023-12-14  职场小达人欢晓    Tags:算法   点击:(165)  评论:(0)  加入收藏
站内最新
站内热门
站内头条