# 为什么在v1架构中tokenier使用线程池而不使用进程池

**URL:** <https://discuss.vllm.ai/t/v1-tokenier/691>\
**Category:** General\
**Created:** [May 26, 2025, 3:47pm UTC](https://discuss.vllm.ai/t/v1-tokenier/691 "2025-05-26T15:47:57Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Easyer](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.vllm.ai/easyer/32/296_2.png) [@Easyer](https://discuss.vllm.ai/u/Easyer)\
**Post date:** [May 26, 2025, 3:47pm UTC](https://discuss.vllm.ai/t/v1-tokenier/691/1 "2025-05-26T15:47:57Z")

</div>

测试拉起1个apiserver，测试并发数目\>100，输入长度\>500的时候，尝试使用进程池，num=5，其端到端的时延明显小于当前的线程池（num=1）方式.  
为什么不使用进程池了？

---

<div class="post-metadata">

**Author:** ![RunLLM](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.vllm.ai/runllm/32/233_2.png) [@RunLLM](https://discuss.vllm.ai/u/RunLLM)\
**Post date:** [May 26, 2025, 3:48pm UTC](https://discuss.vllm.ai/t/v1-tokenier/691/2 "2025-05-26T15:48:28Z")

</div>

vLLM官方推荐在高并发测试时使用进程池（如multiprocessing.Pool）而不是单线程或单进程方式，因为进程池能更好地利用多核CPU资源，提升请求并发能力和吞吐量。实际测试中，进程池（num\>1）下端到端延迟明显低于单线程/单进程（num=1），这是因为多进程能并行发起和处理请求，减少了请求排队和阻塞时间。相关用法可参考[vLLM官方测试脚本](https://github.com/vllm-project/vllm/blob/main/tests/async_engine/test_api_server.py)。

如果你发现官方脚本默认用进程池，主要是为了模拟真实高并发场景，最大化服务器负载和利用率。单线程/单进程方式会因GIL和I/O等待导致并发能力受限，无法充分压测vLLM的极限性能。如需自定义并发方式，可根据实际需求调整进程池或线程池参数。[更多细节见官方文档](https://docs.vllm.ai/en/latest/getting_started/examples/basic.html)。需要详细原理分析吗？

Sources:

- [vLLM官方测试脚本](https://github.com/vllm-project/vllm/blob/main/tests/async_engine/test_api_server.py)
- [更多细节见官方文档](https://docs.vllm.ai/en/latest/getting_started/examples/basic.html)

---

<div class="post-metadata">

**Author:** ![Easyer](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.vllm.ai/easyer/32/296_2.png) [@Easyer](https://discuss.vllm.ai/u/Easyer)\
**Post date:** [May 26, 2025, 3:52pm UTC](https://discuss.vllm.ai/t/v1-tokenier/691/3 "2025-05-26T15:52:55Z")

</div>

我的意思是说vllm/entrypoints/serving\_engine.py中OpenAIServing的\_\_init\_\_初始化方法中，以下代码片段，为什么使用ThreadPoolExecutor， 不使用ProcessPoolExecutor,  
self.\_tokenizer\_executor = ThreadPoolExecutor(max\_workers=1)

---

<div class="post-metadata">

**Author:** ![RunLLM](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.vllm.ai/runllm/32/233_2.png) [@RunLLM](https://discuss.vllm.ai/u/RunLLM)\
**Post date:** [May 26, 2025, 3:53pm UTC](https://discuss.vllm.ai/t/v1-tokenier/691/4 "2025-05-26T15:53:18Z")

</div>

vLLM在OpenAIServing的` __init__ `中使用`ThreadPoolExecutor(max_workers=1)`，而不是`ProcessPoolExecutor`，主要原因是HuggingFace的tokenizer对象通常不是进程安全的，且其初始化和序列化（pickle）开销较大，跨进程传递会导致性能下降和兼容性问题。此外，tokenizer大多为Rust实现，线程池下能释放GIL，获得并发加速，而进程池反而带来不必要的IPC和内存开销。相关讨论见[官方PR说明](https://github.com/vllm-project/vllm/pull/10635)。

综上，线程池（单线程）既保证了线程安全，又避免了进程池的高昂代价和复杂性，是当前vLLM推荐的做法。如需详细原理或对比分析，请告知。

Sources:

- [官方PR说明](https://github.com/vllm-project/vllm/pull/10635)
