部署扩散模型时,一个基本的架构选择在于系统如何处理推理 (inference)请求。考虑到扩散模型通常需要大量的计算时间(每次生成从几秒到几分钟),同步处理与异步处理的选择直接影响用户体验、资源使用和系统扩展能力。
同步处理:直接请求与响应
当使用同步模型时,客户端向推理 (inference)API发送请求并等待,保持连接开放,直到生成完成并将结果(例如生成的图像或错误)在同一响应中返回。
一个基本的同步请求流程。客户端等待服务器完成生成。
特点:
- 简单: 从客户端的角度来看,这直接简单。发送请求,获取响应。服务器端的逻辑最初看起来也更简单。
- 即时反馈(理论上): 如果生成是即时的,客户端将获得即时反馈。然而,对于扩散模型而言,“即时”可能意味着几十秒甚至更长。
- 阻塞性: 客户端应用程序被阻塞,等待响应。对于Web应用程序,这通常意味着用户会看到长时间的加载指示。与请求关联的服务器连接在整个持续时间内被占用。
- 资源效率低下: 长时间保持网络连接开放会消耗服务器资源(内存、连接槽),即使主要瓶颈是GPU计算。Web服务器和负载均衡器可能会对长时间运行的请求超时。
- 扩展能力挑战: 处理许多并发的长时间同步请求会迅速耗尽服务器资源,并可能导致性能不佳或请求失败。基于活跃连接的自动扩展可能具有误导性,因为连接可能处于等待状态而非积极消耗计算资源。
对于典型的扩散模型使用场景,如果生成时间超过几秒,同步处理通常不适用于面向用户的应用程序。它可能只适用于内部工具或API,其中调用者被设计用于处理长时间等待,或者如果扩散过程经过高度优化,能够持续在不到一两秒内执行完成。
异步处理:请求与获取分离
在异步模型中,客户端发送请求,API服务器立即确认接收,通常返回一个任务ID或状态URL。实际的计算在后台进行,与初始请求-响应周期分离。客户端必须稍后检查状态(轮询)或在结果准备好时接收通知(Webhook/WebSocket)。
一个使用轮询的异步请求流程。客户端接收一个ID,稍后回头检查结果。
特点:
- 非阻塞性: 初始API请求快速返回,释放客户端应用程序。用户体验可以围绕此进行设计,允许用户在生成在后台进行时执行其他操作。
- 扩展能力提升: 前端API服务器快速处理确认,并能管理大量传入请求,而不受长时间计算时间的束缚。实际工作负载通常由一个独立的工人池管理,它们从队列中处理任务。
- 资源效率: 处理连接的服务器资源短暂使用。计算密集型工作由专用工作程序处理,它们通常根据队列长度或处理负载独立扩展。
- 容错性: 如果处理任务的工作程序失败,该任务通常可以从队列中重试,而无需客户端重新提交原始请求。
- 增加的复杂性: 此模式引入了更多组件:
- 任务队列: (例如,RabbitMQ、Redis Streams、AWS SQS、Google Pub/Sub)用于在API和工作程序之间缓冲请求。
- 后台工作程序: 一个进程或服务池,它们从队列中获取任务并执行扩散模型推理 (inference)。这些工作程序需要访问GPU。
- 结果存储: 一个存储生成输出的地方(例如,S3、GCS、数据库Blob存储),与任务ID关联。
- 状态/通知机制: 一个用于轮询的端点,或一个用于推送通知(Webhook、WebSocket)的系统,以通知客户端结果何时准备好。
- 客户端逻辑: 客户端需要处理异步流程:提交请求、存储任务ID、实施轮询或监听通知,以及获取结果。
以下是一个简化的架构图,说明了异步系统中经常涉及的组件:
扩散模型推理异步架构的总体视图。
如何选择
对于扩散模型的同步和异步处理的选择,生产系统通常倾向于选择异步,因为涉及的典型推理 (inference)时间。
-
何时使用同步:
- 您的模型和硬件经过优化,能够持续非常快速地生成结果(例如,持续在2-3秒内完成)。
- 应用程序的用户体验能容忍短暂的阻塞等待。
- 预期负载较低,或者您有足够的资源在整个持续时间内处理峰值并发连接。
- 对于长时间任务,实现简单性是绝对的最高优先级,高于扩展能力和用户体验。
-
何时使用异步:
- 生成时间可变或经常超过几秒。
- 您需要同时处理中等至高量的请求。
- 需要非阻塞的用户体验,允许用户在生成进行时继续交互。
- 您需要高效利用服务器资源,并对API处理和计算工作程序进行独立扩展。
- 抵抗工作程序故障的容错性很重要。
虽然异步系统引入了更多的活动部分,但在大规模部署计算密集型扩散模型时,其在用户体验、扩展能力和资源管理方面的益处通常超过了增加的复杂性。理解这种权衡对于设计一个能够满足性能和可靠性要求的系统架构非常重要。