共计 3548 个字符,预计需要花费 9 分钟才能阅读完成。
BentoML 是一个开源的大语言模型(LLM)AI 利用的开发框架和部署工具,致力于为开发者提供最简略的构建大语言模型 AI 利用的能力,其开源产品曾经反对寰球数千家企业和组织的外围 AI 利用。
当 BentoML 在 Serverless 环境中部署模型时,其中一个次要挑战是冷启动慢,尤其在部署大型语言模型时更为显著。因为这些模型体积宏大,启动和初始化过程耗时很长。此外,因为 Image Registry 的带宽较小,会让大体积的 Container Image 进一步加剧冷启动迟缓的问题。为了解决这一问题,BentoML 引入了 JuiceFS。
JuiceFS 的 POSIX 兼容性和数据分块使咱们可能按需读取数据,读取性能靠近 S3 能提供的性能 的下限,无效解决了大型模型在 Serverless 环境中冷启动迟缓的问题。 应用 JuiceFS 后,模型加载速度由原来的 20 多分钟缩短至几分钟。 在施行 JuiceFS 的过程中,咱们发现理论模型文件的读取速度与预期基准测试速度存在差别。通过一系列优化措施,如改良数据缓存策略和优化读取算法,咱们胜利解决了这些挑战。在本文中,咱们将具体介绍咱们面临的挑战、解决方案及相干优化。
01 BentoML 简介以及 Bento 的架构
在介绍模型部署环节的工作之前,首先须要对 BentoML 是什么以及它的架构做一个简要的介绍。
BentoML 是一个高度集成的开发框架,采纳简略易用的形式,反对以开发单体利用的形式进行开发,同时以分布式应用的模式进行部署。这意味着开发者能够用很低的学习老本来疾速开发一个高效利用硬件资源的大语言模型 AI 利用。BentoML 还反对多种框架训练进去的模型,包含 PyTorch、TensorFlow 等罕用 ML 框架。起初,BentoML 次要服务于传统 AI 模型,但随着大型语言模型的衰亡,如 GPT 的利用,BentoML 也可能服务于大语言模型。
BentoML 产生的制品称为 Bento,Bento 的角色相似于 Container Image,是用于 AI 利用部署的最根本单位,一个 Bento 能够轻松部署在不同的环境中,比方 Docker、EC2、AWS Lambda、AWS SageMaker、Kafka、Spark、Kubernetes。
一个 Bento 蕴含了业务代码、模型文件、动态文件,同时咱们形象进去了 API Server 和 Runner 的概念,API Server 是流量的入口,次要承载一些 I/O 密集型的工作,Runner 通常是执行模型的推理工作,次要承载一些 GPU/CPU 密集型的工作,从而能够将一个 AI 利用中不同硬件资源需要的工作进行轻松解耦。
BentoCloud 是一个使 Bento 能够部署在云上的平台,个别开发工作分为三个阶段:
- 第一阶段:开发阶段
当我的项目应用 BentoML 进行 AI App 开发时,产生制品 Bento。此阶段 BentoCloud 的角色是 Bento Registry。
- 第二阶段:集成阶段
若要将 Bento 部署到云环境中,须要一个 OCI 镜像(Container Image)。在这个阶段,咱们有一个组件称为 yatai-image-builder,负责将 Bento 构建成 OCI 镜像,以便后续利用。
- 第三阶段:部署阶段,也是本文的重点内容
这其中一个要害组件是 yatai-serverless。在这个阶段,yatai-serverless 负责将上一阶段构建的 OCI 镜像部署到云上。
02 Serverless 平台部署大模型的挑战
- 挑战 1:冷启动慢
对于 Serverless 平台而言,冷启动工夫至关重要。设想一下,当申请达到时,从零开始减少正本,这可能须要超过 5 分钟。在这段时间内,后面的某些 HTTP 基础设施可能认为曾经超时,对用户体验不利。特地是对于大语言模型,其模型文件通常很大,可能达到十几到二十几 GB 的规模,导致在启动时拉取和下载模型的阶段十分耗时,从而显著缩短冷启动工夫。
- 挑战 2:数据一致性问题
这是 Serverless 平台中特有的问题。咱们的平台通过对 Bento 的一些建模解决了这些问题。
- 挑战 3:数据安全性问题
这是将 Bento 部署到云上的次要起因之一,也是 BentoML 提供给用户的外围价值之一。家喻户晓,OpenAI 以及国内的一些大语言模型会提供一些 HTTP API 供用户应用,但因为许多企业或利用场景对数据安全性有极高的要求,因而他们不可能将敏感数据传递给第三方平台的 API 进行解决。他们心愿将大型语言模型部署到本人的云平台上,以确保数据的安全性。
03 为什么应用 JuiceFS?
接下来将具体探模型部署这一要害阶段的具体工作。下图展现了咱们最后采纳的架构,行将所有模型文件,包含 Python 代码、Python 依赖和扩大,都打包成一个 Container Image,而后在 Kubernetes 上运行。然而,这一流程面临着以下挑战:
- 首先,一个 Container Image 由一系列 Layer 组成,因而 Container Image 最小的下载和缓存单位是 Layer,尽管在下载 Container Image 时,Container Image 的 Layer 是并行下载的,但 Layer 在解压的时候是串行的。当解压到模型所在的 Layer 时速度会减慢,同时占用大量的 CPU 工夫。
- 另一个挑战是当不同的 Bento 应用雷同的模型时。这种架构会节约多份雷同的空间,并且被打包到不同的 Image 中,作为不同 Layer 存在,导致了屡次下载和解压,这是极大的资源节约。因而,这种架构无奈共享模型。
在解决这个问题时,咱们首选了 JuiceFS,次要因为它具备以下三个劣势。
- 首先,它采纳 POSIX 协定,无需再加一层形象就使咱们可能以连贯的形式读取数据。
- 其次,它能够达到很高的吞吐,能够靠近整个 S3 或 GCS 的带宽。
- 第三,它可能实现良好的共享模型。当咱们将模型存储在 JuiceFS 中时,不同实例能够共享同一个大型语言模型。
下图是咱们集成 JuiceFS 后的架构。在构建 Container Image 时,咱们将模型独自提取并存储到 JuiceFS 中。Container Image 中仅蕴含用户的 Python 业务代码和 Python 运行所需的依赖和根底环境,这样的设计带来的益处是能够同时下载模型和运行,无需在本地解压模型。整体解压过程变得十分迅速,下载的数据量也大大减少,从而显著晋升了下载性能。
此外,咱们进一步优化了下载和缓存的颗粒度,不仅每个模型都有本人的缓存颗粒度,而且 JuiceFS 对大文件宰割成了一系列 chunk,以 chunk 为单位进行下载和缓存,利用这个个性能够实现相似于大模型的 Stream Loading 的成果。
咱们还充分利用了 GKE 的 Image Streaming 技术。通过 Model Streaming 和 Image Streaming 同时进行数据拉取,咱们胜利升高了启动工夫,晋升了整体性能。
04 集成 JuiceFS 时遇到的挑战
- 挑战 1:无缝集成
在引入 JuiceFS 这一新组件时,必须解决如何与已有组件实现无缝集成的问题。这种状况是在任何较为成熟的平台引入新组件时都会遇到的广泛挑战。为了更好地继承 JuiceFS,咱们采纳了 AWS MemoryDB,以代替本人运维的 Redis,从而升高架构的复杂度。
- 挑战 2: 引入新组件对业务逻辑的影响
引入 JuiceFS 可能导致业务逻辑的变动。之前,Bento 的容器镜像蕴含了残缺的模型,而当初的 Bento 容器镜像则不再携带模型。在 yatai-serverless 平台的部署中,咱们必须在代码层面确保这两种不同的镜像在业务逻辑上实现互相兼容。为此,咱们应用不同的 label 来辨别不同版本的 bento,而后在代码逻辑里做向前兼容。
- 挑战 3: JuiceFS 下载速度问题
在测试 JuiceFS 时发现,应用 JuiceFS 下载模型的速度十分慢,甚至比间接从镜像中下载还要慢。通过 JuiceFS 团队的帮助,咱们发现咱们的 Boot Disk 是网络磁盘,所以咱们始终应用网络磁盘作为 JuiceFS 的缓存盘,这就会导致一个奇怪的景象:不命中缓存时速度更快,一旦命中缓存就变慢。为了解决这个问题,咱们为咱们的 GKE 环境都增加了 Local NVME SSD,并将 Local NVMe SSD 作为 JuiceFS 的缓存盘,从而完满地解决了这一问题。
05 瞻望
在将来,咱们将深刻进行更多的可观测性工作,以确保整个架构保持良好的运行状态,并取得足够的指标以便更好地优化配置,尽量避免再次出现相似的问题。
心愿能够高效利用 JuiceFS 自带的缓存能力。例如,将模型提前种植到 JuiceFS 后,这意味着在业务集群中,能够提前在节点中预热模型的缓存,从而进一步晋升缓存和冷启动工夫的性能。
心愿这篇内容可能对你有一些帮忙,如果有其余疑难欢送退出 JuiceFS 社区与大家独特交换。