版本
main @ d3551f3
问题描述
ContextImpl::ContextImpl() 把默认 runtime 的设备号硬编码为 0:
// src/infinicore/context/context_impl.cc
runtime_table_[i][0] = std::unique_ptr<Runtime>(new Runtime(Device(Device::Type(i), 0)));
而 Runtime 的构造函数会建 primary context、一条流(infinirtStreamCreate)、一个 infiniop handle 和两个分配器。
结果是:任何进程只要使用非 0 号卡,都会在 0 号卡上额外建一整套 runtime,尽管它从不在 0 号卡上做任何计算。 PyTorch 没有这个行为,它只在实际使用的卡上建 context。
在「一进程一张卡」的张量并行场景下这会累积。实测 vLLM TP=4:0 号卡上有 4 个进程,而对照的 vllm-metax 只有 2 个。在 MetaX C550 / MACA 3.8.0.23 上这会让 TP>=4 挂死在驱动的无限重试里(mxkwCreateQueueBlock ioctl create queue block timeout);去掉这个多余的 runtime 后,16/16 个用例全部跑通。驱动为何因此超时我们没有定论,不属于本 issue 的范围。
如何复现
单进程即可,不需要多卡框架,也不需要 PyTorch。绑到 3 号卡做一次分配:
python -c "import os,time,infinicore; \
infinicore.zeros((4,4), dtype=infinicore.float32, device=infinicore.device('cuda',3)); \
print('PID', os.getpid()); time.sleep(60)"
另开一个终端看 mx-smi 的进程表:
| GPU PID Process Name GPU Memory(MiB) |
| 0 1356394 python 0 | <- 多余的
| 3 1356394 python 4 |
同一个 PID 同时出现在 0 号卡和 3 号卡上。
补充:先调用 infinicore.set_device(3) 不能规避,因为 ContextImpl::setDevice() 会先调 getCurrentRuntime() 做比较,而这一步就已经把 0 号卡的默认 runtime 惰性建出来了。
预期结果
进程只在它实际使用的卡上建立 runtime;默认设备号应当可以由嵌入方指定,而不是恒为 0。
版本
main@ d3551f3问题描述
ContextImpl::ContextImpl()把默认 runtime 的设备号硬编码为0:而
Runtime的构造函数会建 primary context、一条流(infinirtStreamCreate)、一个 infiniop handle 和两个分配器。结果是:任何进程只要使用非 0 号卡,都会在 0 号卡上额外建一整套 runtime,尽管它从不在 0 号卡上做任何计算。 PyTorch 没有这个行为,它只在实际使用的卡上建 context。
在「一进程一张卡」的张量并行场景下这会累积。实测 vLLM TP=4:0 号卡上有 4 个进程,而对照的
vllm-metax只有 2 个。在 MetaX C550 / MACA 3.8.0.23 上这会让 TP>=4 挂死在驱动的无限重试里(mxkwCreateQueueBlock ioctl create queue block timeout);去掉这个多余的 runtime 后,16/16 个用例全部跑通。驱动为何因此超时我们没有定论,不属于本 issue 的范围。如何复现
单进程即可,不需要多卡框架,也不需要 PyTorch。绑到 3 号卡做一次分配:
另开一个终端看
mx-smi的进程表:同一个 PID 同时出现在 0 号卡和 3 号卡上。
补充:先调用
infinicore.set_device(3)不能规避,因为ContextImpl::setDevice()会先调getCurrentRuntime()做比较,而这一步就已经把 0 号卡的默认 runtime 惰性建出来了。预期结果
进程只在它实际使用的卡上建立 runtime;默认设备号应当可以由嵌入方指定,而不是恒为 0。