多个独立问题:批量为一次请求还是拆分为多个?——LLM 并发处理分析

发布: (2026年5月3日 GMT+8 08:19)
9 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的具体内容(文章正文、代码块之外的文字),我将为您翻译成简体中文并保持原有的格式和 Markdown 语法。

哪个更快?

简短回答:
将问题拆分为 多个相互独立的并行请求 几乎总是更快。

为什么? – 从第一性原理看 LLM 的“写作”方式

步骤发生了什么延迟影响
Autoregressive generation模型一次生成 一个 token,将其追加到提示中,然后生成下一个 token。N tokens → N forward passes
Prefill整个输入提示只处理一次,以构建 KV‑cache。与输入长度线性相关
DecodeToken 按顺序(逐个)生成。主导总体延迟

后果

  • 一个 100‑token 的答案大约需要 100 次推理步骤。
  • 一个 500‑token 的答案大约需要 500 次推理步骤。
  • 输出总长度直接决定总延迟。

场景:5 个独立问题,每个约 200 Token

方法 A – 将所有问题合并为一个请求

Please answer the following questions separately:
1. …
2. …
3. …
4. …
5. …

模型需要做的事情

  • 预填充: 处理一个的拼接提示(所有 5 个问题)。
  • 解码: 生成 ≈ 5 × 200 = 1000 个 token 顺序进行。
  • 额外开销:
    • 上下文切换(“现在回答问题 3”)。
    • 更大的 KV‑cache → 每步更多注意力计算。
    • 格式化/过渡文本常常使 token 数超过 1000。

估计延迟 ≈ 1000 × (每 token 生成时间)。

方法 B – 并行发送 5 个独立请求

每个请求包含一个问题,生成 ≈ 200 个 token。

服务器的工作方式

  • 预填充: 每个请求的提示更短。
  • 解码: 5 条独立的解码流 并行 运行(或一起批处理)。
  • 现代推理引擎(vLLM、TensorRT‑LLM、TGI 等)使用 连续批处理:单次 GPU 前向传播可以同时为 5 个请求各生成一个 token。

估计延迟 ≈ max(单个请求延迟)≈ 200 × (每 token 生成时间)。

直接比较

方法总输出 Token 数大致延迟(相对)
合并请求~1000+~1000 次解码步骤(顺序)
5 个并行请求~200 每个~200 次解码步骤(并行)

理论加速比: ~5×(等于问题数量)。

为什么服务器端的并行请求更快

  1. 连续批处理 – GPU 在并行矩阵运算方面表现出色。

    • 5 个短请求 → 5‑路批处理 前向传播,每一步产生 5 个 token。
    • 1 个长请求 → 单序列前向传播,每一步仅产生 1 个 token。
  2. 更高的 GPU 利用率 – 批处理许多短序列可以让 GPU 保持忙碌,而单个长序列会浪费并行能力。

  3. Prefill 与 Decode

    • 合并: 更长的 prefill + 更长的 decode。
    • 拆分: 每个请求的 prefill 更短;所有 prefill 可以流水化或并发运行,每个 decode 也很短。

质量考量(超越速度)

问题合并提示拆分请求
注意力稀释无关的上下文可能降低答案质量(“中途失焦”)。完全集中在单一问题上。
格式错误更容易出现编号/遗漏错误。输出独立 → 格式更整洁。
错误传播Q2 的错误可能影响 Q3‑Q5(自回归惯性)。错误仅局限于出错的请求。

当合并仍可能合理时

情况原因
隐藏的相关性如果问题之间有关联(例如,同一报告的不同部分),共享上下文可以提升一致性。
严格的 API 速率限制如果只能每分钟调用 3 次,可能需要合并请求。
网络延迟占主导非常高的往返延迟(例如 > 2 秒)可能导致 5 次单独调用比一次合并调用更慢。现代 API 通常在 100‑300 毫秒之间,这种情况很少见。
极短的答案当每个答案只有一两个词时,前置填充的开销占主导;一次请求可以减少冗余的前置填充。

快速经验基准(异步 Python)

import asyncio
import time
import aiohttp

API_URL = "https://api.your-llm.com/v1/completions"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

async def ask_single(session, prompt):
    start = time.time()
    async with session.post(
        API_URL,
        json={"model": "gpt-4o-mini", "prompt": prompt, "max_tokens": 300},
        headers=HEADERS,
    ) as resp:
        await resp.json()          # ignore content, just wait for response
    return time.time() - start

async def benchmark():
    questions = [
        "Question 1: …",
        "Question 2: …",
        "Question 3: …",
        "Question 4: …",
        "Question 5: …",
    ]

    async with aiohttp.ClientSession() as session:
        # ---- Approach A: Combined -------------------------------------------------
        combined_prompt = "Please answer each question separately:\n" + "\n".join(questions)
        t_combined = await ask_single(session, combined_prompt)

        # ---- Approach B: Parallel -------------------------------------------------
        tasks = [ask_single(session, q) for q in questions]
        t_parallel = max(await asyncio.gather(*tasks))

        print(f"Combined request latency : {t_combined:.2f}s")
        print(f"Parallel requests latency: {t_parallel:.2f}s")
        print(f"Speed‑up factor          : {t_combined / t_parallel:.2f}×")

if __name__ == "__main__":
    asyncio.run(benchmark())

多次运行脚本后,你通常会看到并行版本在处理独立的中等长度答案时快约 4‑5 倍。

TL;DR

  • 速度: 5 个并行请求 ≈ 比单个合并请求快 5 倍(前提是服务能够批处理它们)。
  • 质量: 并行请求让模型的注意力保持集中,避免跨问题的相互干扰。
  • 例外情况: 仅在问题真正相互依赖、受到严格速率限制,或网络延迟远大于生成时间时才考虑合并。

结论: 当问题相互无关时,发起 独立的并发请求。 🚀

并行 vs. 合并请求

# Parallel execution
start = time.time()
await asyncio.gather(*[ask_single(session, q) for q in questions])
time_parallel = time.time() - start

print(f"Combined: {time_combined:.2f}s")
print(f"Parallel: {time_parallel:.2f}s")
print(f"Speedup: {time_combined / time_parallel:.1f}x")

在实际使用中,5 个中等复杂度的独立问题 通常能够通过并行请求获得 3–5 倍的加速

对比

维度合并请求拆分并行请求
生成速度慢(所有答案顺序输出)快(并行生成,延迟等于最慢的)
GPU 利用率低(单序列推理)高(批量并行推理)
答案质量可能下降(注意力稀释)更好(上下文隔离)
API 调用次数1N(每个问题一次)
最佳适用场景受速率限制 / 极短答案需要详细答案的独立问题

核心原则(一句话)
LLM 的自回归机制意味着输出是顺序的;合并请求会将所有输出强制为单一的串行流,而拆分请求则利用服务器端的并行性同时生成多个输出——这是一种使用更多并发槽位(空间)来换取时间的经典权衡。

0 浏览
Back to Blog

相关文章

阅读更多 »