Gradio 代理与 MCP 黑客马拉松

获奖者
Gradio logo
  1. 其他教程
  2. 设置演示以实现最佳性能

设置演示以实现最佳性能

假设你的 Gradio 演示在社交媒体上 爆红 —— 有大量用户同时试用,你希望为用户提供最佳体验,换句话说,就是最大限度地减少每个用户在队列中等待查看预测结果的时间。

你如何配置你的 Gradio 演示来处理最多的流量?本指南将深入探讨 Gradio 的 .queue() 方法的一些参数以及其他相关参数,并讨论如何设置这些参数,以便以最小的延迟同时为大量用户提供服务。

这是一份高级指南,因此请确保你已经了解 Gradio 的基础知识,例如如何创建和启动 Gradio 界面。本指南中的大部分信息无论你是将演示托管在Hugging Face Spaces 上还是在自己的服务器上都适用。

Gradio 排队系统概述

默认情况下,每个 Gradio 演示都包含一个内置的排队系统,可以扩展到处理数千个请求。当你的应用用户提交请求(即向你的函数提交输入)时,Gradio 会将该请求添加到队列中,请求通常按顺序处理(正如后面讨论的,这并非完全准确)。当用户的请求处理完成后,Gradio 服务器会使用服务器发送事件 (SSE) 将结果返回给用户。SSE 协议相比简单使用 HTTP POST 请求有几个优势:

(1) 它们不会超时——如果大多数浏览器在短时间内(例如 1 分钟)没有收到 POST 请求的响应,就会引发超时错误。如果你的推理函数运行时间超过 1 分钟,或者许多人同时试用你的演示,导致延迟增加,这可能会成为问题。

(2) 它们允许服务器向前端发送多个更新。这意味着,例如,服务器可以实时发送你的预测完成所需时间的预计到达时间 (ETA)。

要配置队列,只需在启动 InterfaceTabbedInterfaceChatInterface 或任何 Blocks 之前调用 .queue() 方法即可。示例如下:

import gradio as gr

app = gr.Interface(lambda x:x, "image", "image")
app.queue()  # <-- Sets up a queue with default parameters
app.launch()

请求如何从队列中处理

当 Gradio 服务器启动时,一个线程池用于执行队列中的请求。默认情况下,此线程池的最大大小为 40(这是从 FastAPI 继承的默认值,Gradio 服务器基于 FastAPI)。然而,这并 意味着队列中总是并行处理 40 个请求。

相反,Gradio 默认使用单函数-单工作器模型。这意味着每个工作器线程仅从所有可能构成 Gradio 应用的函数中分配一个函数。这确保了你不会因为多个工作器同时调用机器学习模型而出现内存不足错误。假设你的 Gradio 应用中有 3 个函数:A、B 和 C。你看到用户使用你的应用时传入了以下 7 个请求序列:

1 2 3 4 5 6 7
-------------
A B A A C B A

最初,将分派 3 个工作器来处理请求 1、2 和 5(对应函数:A、B、C)。一旦其中任何一个工作器完成,它们将开始处理队列中相同函数类型的下一个函数,例如,完成处理请求 1 的工作器将开始处理请求 3,依此类推。

如果你想改变这种行为,有几个参数可用于配置队列并帮助减少延迟。让我们逐一介绍它们。

queue() 中的 default_concurrency_limit 参数

我们将探讨的第一个参数是 queue() 中的 default_concurrency_limit 参数。它控制有多少工作器可以执行同一个事件。默认情况下,此参数设置为 1,但你可以将其设置为更高的整数:210,甚至是 None(在最后一种情况下,除了可用工作器总数之外没有其他限制)。

例如,如果你的 Gradio 应用不调用任何资源密集型函数,这会很有用。如果你的应用只查询外部 API,那么你可以将 default_concurrency_limit 设置得更高。增加此参数可以线性倍增你的服务器处理请求的能力

那么为什么不一直将这个参数设置得很高呢?请记住,由于请求是并行处理的,每个请求都会消耗内存来存储处理所需的数据和权重。这意味着如果你将 default_concurrency_limit 设置得过高,可能会遇到内存不足错误。如果 default_concurrency_limit 过高,由于在不同工作器线程之间切换的开销,你也可能会开始出现收益递减的情况。

建议:在继续看到性能提升或达到机器内存限制之前,尽可能提高 default_concurrency_limit 参数。你可以在此处阅读 Hugging Face Spaces 机器规格

事件中的 concurrency_limit 参数

你还可以单独为每个事件设置可以并行处理的请求数量。这些设置优先于之前描述的 default_concurrency_limit 参数。

要实现这一点,请设置任何事件监听器的 concurrency_limit 参数,例如 btn.click(..., concurrency_limit=20) 或在 InterfaceChatInterface 类中设置:例如 gr.Interface(..., concurrency_limit=20)。默认情况下,此参数设置为全局 default_concurrency_limit

launch() 中的 max_threads 参数

如果你的演示使用非异步函数,例如 def 而不是 async def,它们将在线程池中运行。此线程池的大小为 40,这意味着只能创建 40 个线程来运行你的非异步函数。如果你遇到此限制,可以使用 max_threads 增加线程池大小。默认值为 40。

提示: 你应该尽可能使用异步函数来增加你的应用可以处理的并发请求数量。非 CPU 密集型的快速函数是编写为 `async` 的好选择。这篇指南是关于这个概念的很好入门。

queue() 中的 max_size 参数

一个更直接的减少等待时间的方法是简单地阻止太多人一开始就加入队列。你可以使用 queue()max_size 参数设置队列处理的最大请求数量。如果请求到达时队列已达到最大大小,它将不被允许加入队列,相反,用户将收到一个错误,提示队列已满,请重试。默认情况下,max_size=None,这意味着加入队列的用户数量没有限制。

矛盾的是,设置 max_size 通常可以改善用户体验,因为它阻止了用户因非常长的队列等待时间而却步。对你的演示更感兴趣和投入的用户会继续尝试加入队列,并能够更快地获得结果。

建议:为了更好的用户体验,根据你对用户愿意等待预测时间的预期,设置一个合理的 max_size

事件中的 max_batch_size 参数

增加 Gradio 演示并行性的另一种方法是编写你的函数,使其能够接受批量输入。大多数深度学习模型处理批量样本比处理单个样本效率更高。

如果你编写函数来处理批量样本,Gradio 将自动将传入请求批量处理,并将它们作为批量样本传递给你的函数。你需要将 batch 设置为 True(默认情况下为 False),并根据你的函数能够处理的最大样本数量设置一个 max_batch_size(默认情况下为 4)。这两个参数可以传递给 gr.Interface() 或 Blocks 中的事件,例如 .click()

虽然设置批量处理在概念上与让工作器并行处理请求类似,但对于深度学习模型来说,它通常比设置 concurrency_count 更快。缺点是你可能需要稍微调整你的函数以接受批量样本而不是单个样本。

以下是一个不接受批量输入的函数示例——它一次处理一个输入

import time

def trim_words(word, length):
    return word[:int(length)]

以下是同一个函数,经过重写以接受批量样本

import time

def trim_words(words, lengths):
    trimmed_words = []
    for w, l in zip(words, lengths):
        trimmed_words.append(w[:int(l)])
    return [trimmed_words]

第二个函数可以与 batch=True 和适当的 max_batch_size 参数一起使用。

建议:如果可能,编写你的函数以接受批量样本,然后将 batch 设置为 True,并根据机器的内存限制将 max_batch_size 设置得尽可能高。

升级你的硬件(GPU、TPU 等)

如果你已经完成了以上所有操作,但你的演示仍然不够快,你可以升级模型运行的硬件。将模型从在 CPU 上运行更改为在 GPU 上运行,通常会使深度学习模型的推理时间提高 10 到 50 倍。

在 Hugging Face Spaces 上升级你的硬件特别简单。只需点击你的 Space 中的“设置”选项卡,然后选择你想要的 Space 硬件即可。

虽然你可能需要调整部分机器学习推理代码以在 GPU 上运行(如果你使用 PyTorch,这里有一个方便的指南),但 Gradio 完全不依赖于硬件选择,无论你使用 CPU、GPU、TPU 或任何其他硬件,它都能正常工作!

注意:你的 GPU 内存与 CPU 内存不同,因此如果你升级硬件,可能需要调整上面描述的 default_concurrency_limit 参数的值。

结论

恭喜!你现在知道如何设置 Gradio 演示以实现最佳性能。祝你的下一个演示爆红成功!