进程与线程的关键区别
线程共享进程内的 Python 对象;独立进程有自己的地址空间。进程之间交换工作和结果,需要相应的传输机制,不能把一个普通全局列表当作天然共享列表。
实验沿用转换脚本的 conversion_worker 名称,把模型转换替换成平方计算,只观察 spawn、Pool 和 starmap。
import multiprocessing
import subprocess
import sys
def conversion_worker(value):
return value * value
if __name__ == "__main__":
ctx = multiprocessing.get_context("spawn")
with ctx.Pool(2) as pool:
print("pool", pool.starmap(conversion_worker, [(2,), (3,)]))
result = subprocess.run(
[sys.executable, "-c", "print('child')"],
check=True, capture_output=True, text=True,
)
print("subprocess", result.stdout.strip())
下载并运行本节 example.py。只使用 Python 标准库;推荐 Python 3.12,最低 Python 3.11。
运行结果:
pool [4, 9]
subprocess child
starmap 把每一项参数元组展开传给 worker,并收集结果。入口保护让 spawn 启动的子解释器导入模块时,不会再次无限创建进程池。worker 放在模块顶层,也便于新进程按名称找到它。
Slime 里的对应职责
转换工具把权重分片交给进程池;部署代码用 multiprocessing.Process 启动路由或模型服务;subprocess 启动已有外部程序。它们都创建进程,但调用合同不同。
展开 Slime 源码:模型转换进程池
模型转换进程池tools/convert_torch_dist_to_hf_parallel.py · L511–L530
快照 2f2318653f6f794dddd321eff7c9d4b7b174643f· 查看固定版本源码
ctx = multiprocessing.get_context("spawn")
with ctx.Pool(num_workers) as pool:
results = pool.starmap(
conversion_worker,
[
(
i,
key_chunks[i],
args,
megatron_args,
args.model_name,
state_dict_metadata_dict,
load_max_workers,
save_max_workers,
)
for i in range(num_workers)
],
)
final_weight_map = {}展开 Slime 源码:_start_router
_start_routerslime/backends/sglang_utils/deployment.py · L49–L62
快照 2f2318653f6f794dddd321eff7c9d4b7b174643f· 查看固定版本源码
router_args.disable_health_check = True
logger.info(f"Launch router with args: {router_args}")
process = multiprocessing.Process(
target=run_router,
args=(router_args,),
)
process.daemon = True
process.start()
time.sleep(3)
assert process.is_alive()
logger.info(f"Router launched at {router_ip}:{router_port}, Prometheus port: {router_args.prometheus_port}")
return router_ip, router_port| 机制 | 执行什么 | 结果怎样回来 |
|---|---|---|
Pool.starmap | Python worker 函数 | 进程池收集 Python 返回值 |
Process(target=...) | 一个指定的 Python 入口 | 需要另行安排 Queue、Pipe、文件或其他通信 |
subprocess.run/Popen | 外部命令 | 返回码、stdout、stderr 等 |
超时与退出不能混用
Popen.communicate(timeout=...) 超时不会自动替你杀死子进程;后续要明确终止、等待和收集输出。信号与进程组操作属于系统边界,也不能当作 asyncio Task.cancel 的同义词。
Slime 的 signal.alarm 超时和 fcntl.flock 文件锁是其他配套机制,平台适用范围需要单独核对。完整位置在用法索引中。
复述检查
await 不会把任务变成独立进程。进程池有自己的启动、通信和回收成本;同步的 starmap 等待也不能直接放进事件循环里就称为非阻塞。
语义核对:multiprocessing、subprocess。
本节对应的全部源码位置
下面把同类用法在 Slime 中的每个扫描位置接回本节讲解;点击文件名可查看完整源码快照。重复出现的 API 共用解释,具体输入与清理由所在函数决定。
展开本节 2 条源码记录
| 记录 / 讲解 | 源码位置 | 原代码 |
|---|---|---|
| occ-002282 有接收者线索 | tools/convert_torch_dist_to_hf_parallel.py:512 <module> | with ctx.Pool(num_workers) as pool: |
| occ-002283 有接收者线索 | tools/convert_torch_dist_to_hf_parallel.py:513 <module> | results = pool.starmap( |
专题首页 · 上一节 · 下一节:13 · Future、回调与跨线程事件循环 · 源码与教程对照 · 全部用法