You need to enable JavaScript to run this app. 跨节点multiprocessing Manager无法加载嵌套二维共享列表报错
优惠活动
大模型
产品
解决方案
定价
更多

跨节点multiprocessing Manager无法加载嵌套二维共享列表报错

问题根因定位
  • 核心触发原因:跨节点场景下,嵌套Manager的内层Proxy(内层List、Event)的连接token默认携带服务端本地Unix域套接字路径/回环地址,客户端拿到该token后无法在本地解析对应连接,触发FileNotFoundError。同节点运行正常正是因为本地套接字路径在同节点可被访问,跨节点后该路径对客户端无意义。
  • 代码存在两个明确的配置错误:
    1. 服务端初始化mp.Manager()时未显式绑定对外TCP地址,传入的host、port参数完全未生效,默认走本地Unix域套接字通信,跨节点根本无法连通。
    2. 客户端连接写法错误:先创建了一个本地Manager实例,再手动调用__init__修改连接地址,会导致实例状态混乱,拿到的Proxy在做引用计数校验时会连接错误的本地地址。
可行解决方案(按推荐优先级排序)

方案1:自定义顶层二维结构Proxy(最适配跨节点场景)

完全避免嵌套Proxy的token跨节点传输问题,所有操作通过单一TCP连接走服务端执行,稳定性最高,无额外地址匹配问题。

服务端代码改造

import torch.multiprocessing as mp
from multiprocessing.managers import BaseManager, MakeProxyType
from gala.arguments import get_args

mp.current_process().authkey = b'abc'

# 服务端实际运行的二维共享列表类
class Shared2DEventList:
    def __init__(self, num_rows, num_cols):
        # 内部维护二维结构,不需要暴露给客户端
        self.data = [[mp.Event() for _ in range(num_cols)] for _ in range(num_rows)]
    # 暴露给客户端的调用方法
    def get_event(self, row, col):
        return self.data[row][col]
    def trigger_event(self, row, col):
        self.data[row][col].set()
    def clear_event(self, row, col):
        self.data[row][col].clear()

# 自定义Proxy类型,只允许调用上面暴露的方法
Shared2DListProxy = MakeProxyType('Shared2DListProxy', ['get_event', 'trigger_event', 'clear_event'])

# 自定义Manager类
class ServerManager(BaseManager):
    pass

if __name__ == '__main__':
    mp.set_start_method('spawn')
    args = get_args()
    num_learners = args.num_nodes
    # 注册要暴露的共享实例
    ServerManager.register(
        'get_shared_event_list',
        callable=lambda: Shared2DEventList(num_learners, num_learners),
        proxytype=Shared2DListProxy
    )
    # 显式绑定所有网卡的5000端口,走TCP通信
    server = ServerManager(address=('0.0.0.0', 5000), authkey=b'abc')
    print('start service at 10.107.13.120:5000')
    server.start()
    server.join()

客户端代码改造

import torch.multiprocessing as mp
from multiprocessing.managers import BaseManager, MakeProxyType

mp.current_process().authkey = b'abc'

# 和服务端保持一致的Proxy定义
Shared2DListProxy = MakeProxyType('Shared2DListProxy', ['get_event', 'trigger_event', 'clear_event'])

class ClientManager(BaseManager):
    pass

def make_gossip_buffer(mng, args):
    # 拿到顶层唯一的共享实例,直接调用方法即可
    read_events = mng.get_shared_event_list()
    # 原二维索引访问逻辑替换为对应方法调用
    current_rank = args.rank
    target_event = read_events.get_event(current_rank, target_rank)
    # 业务逻辑处理

def train(args):
    # 直接实例化连接,不要先创建本地Manager
    ClientManager.register('get_shared_event_list', proxytype=Shared2DListProxy)
    proc_manager = ClientManager(address=('10.107.13.120', 5000), authkey=b'abc')
    proc_manager.connect()
    make_gossip_buffer(proc_manager, args)

if __name__ == "__main__":
    mp.set_start_method('spawn')
    train(args)

方案2:扁平一维列表替换嵌套结构

如果不想调整自定义Proxy,可将二维结构拍平为一维列表,仅保留一层ListProxy,从根源避免内层Proxy的token跨节点传输问题。

服务端改造

# 原嵌套代码替换为一维扁平结构
total_event_count = num_learners * num_learners
read_events = manager.list([mp.Event() for _ in range(total_event_count)])

客户端访问时手动计算索引

# 原 read_events[rank][target_rank] 替换为索引计算
target_event = read_events[rank * num_learners + target_rank]

配套必须修正的配置

  1. 服务端Manager显式绑定TCP地址,禁止默认Unix套接字:
    # 替换原 manager = mp.Manager()
    manager = mp.Manager(address=('0.0.0.0', 5000), authkey=b'abc')
    
  2. 客户端修正连接写法,禁止手动调用__init__修改实例配置:
    from multiprocessing.managers import BaseManager, ListProxy
    class ClientManager(BaseManager):
        pass
    ClientManager.register('get_read_events', proxytype=ListProxy)
    proc_manager = ClientManager(address=('10.107.13.120', 5000), authkey=b'abc')
    proc_manager.connect()
    

方案3:保留嵌套结构但强制所有Proxy走TCP地址

如果必须保留嵌套ListProxy的结构,需要强制所有内层Proxy的token使用服务端对外TCP地址,禁止默认Unix套接字:

  • 服务端初始化Manager时必须显式传入TCP地址元组(不要传字符串路径),绑定到0.0.0.0对应端口,这样所有后续创建的内层List、Event的Proxy token都会自动使用该TCP地址,不会生成本地套接字路径。
  • 客户端必须按上述规范用BaseManager直接连接,禁止先创建本地Manager再修改配置。
常见排查校验点
  • 客户端拿到Proxy后,打印内层Proxy的_token.address,确认返回值是('10.107.13.120', 5000),如果返回本地文件路径或127.0.0.1地址,说明服务端未正确绑定TCP地址。
  • 确认服务端5000端口在外部可访问,用客户端节点的telnet 10.107.13.120 5000命令测试连通性。
  • 确认服务端和客户端的authkey完全一致,均为bytes类型,无格式错误。

内容的提问来源于stack exchange,提问作者Tobiichi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.03 23:36:01