0. 前言

uccl 的官方 pr 内,看了一下 closed 的 关于 nixl 的 pr 有 37 个。

  • backend API 设计:#186, #212, #755
  • NIXL 语义补齐:#357, #428, #750, #779
  • vLLM 连接器适配:#409
  • 多网络传输实现:#385, #521, #560, #571, #577, #597, #638, #677, #730, #593
  • 其他乱七八糟平台、cicd、安装全都是 pr。。。。。。。。 核心改动就是在uccl_engine.cc,uccl_engine.h这俩文件内。

1. nixl UCCL backend api

nixlBackendEngine 内的 virtual 虚函基本上都有对应的 uccl 实现。具体 uccl 自己实现了下面的:

// src/plugins/uccl/uccl_backend.h
class nixlUcclEngine : public nixlBackendEngine {
public:
    bool supportsRemote() const { return true; }
    bool supportsLocal() const { return false; }
    bool supportsNotif() const { return true; }
  
    nixl_mem_list_t getSupportedMems() const;
    nixl_status_t getPublicData(const nixlBackendMD *meta, std::string &str) const;
    nixl_status_t getConnInfo(std::string &str) const;
    nixl_status_t loadRemoteConnInfo(const std::string &remote_agent, const std::string &remote_conn_info);
    nixl_status_t connect(const std::string &remote_agent) override;
    nixl_status_t disconnect(const std::string &remote_agent);
 
    nixl_status_t registerMem(const nixlBlobDesc &mem, const nixl_mem_t &nixl_mem, nixlBackendMD *&out);
    nixl_status_t deregisterMem(nixlBackendMD *meta);
  
    nixl_status_t loadLocalMD(...);
    nixl_status_t loadRemoteMD(...);
    nixl_status_t prepXfer(...);
    nixl_status_t postXfer(...);
    nixl_status_t checkXfer(...);
    nixl_status_t releaseReqH(...);
    nixl_status_t getNotifs(notif_list_t &notif_list);
    nixl_status_t genNotif(const std::string &remote_agent, const std::string &msg) const override;
  
private:   
    startListener();
    ...
}

2. uccl 侧 northbound

uccl 侧 northbound
supportsRemote()底层支持:uccl_engine_get_metadata()、uccl_engine_connect()、uccl_engine_accept()、uccl_engine_prepare_fifo()、uccl_engine_read_vector()、uccl_engine_write_vector()
supportsNotif()底层支持:uccl_engine_start_listener()、uccl_engine_get_notifs()、uccl_engine_send_notif()
supportsLocal()fasle
supportsProgTh()\
getSupportedMems()uccl_engine_reg()
nixlUcclEngine()
自己本身的构造函数
uccl_engine_create(),(ps:这里 mooncake 也有自己的createTransferEngine()实现),
启一个后台线程 startListener(),持续做 accept。
~nixlUcclEngine()uccl_engine_stop_accept() 让阻塞中的 accept 退出,destroy 所有 MR,所有 conn 以及 engine。
startListener()循环调用uccl_engine_accept() 接受远端连接,对每个新连接调用 uccl_engine_start_listener(),让通知收发通道工作起来。 然后把连接放进 connected_agents_
getConnInfo()对应**uccl_engine_get_metadata()**,把 endpoint 的 unified metadata 变成字符串形式,最终生成类似 ip:port?gpu 的连接串
loadRemoteConnInfo()拿到 NIXL 传下来的 ip/port/gpu_dix 后用**uccl_engine_connect()*建链,建完调用ccl_engine_start_listener(),然后把 remote_agent uccl_conn_t 记到 connected_agents_。
connect()\
disconnect()uccl_engine_conn_destroy()
registerMem()uccl_engine_reg()/uccl_engine_prepare_fifo()/uccl_engine_mr_destroy()
deregisterMem()uccl_engine_mr_destroy()
getPublicData\
loadLocalMD\
loadRemoteMD\
unloadMD\
prepXfer()从前面的connected_agents_ 拿到对应的 uccl_conn_t* ,然后创建 nixlUcclReqH,然后需要我们自己实现一个deserialize 去还原fifo 的格式(charstruct),然后uccl_engine_update_fifo去patch前面 enqueue 的fifo
postXfer()
单边
走uccl_engine_read_vector()或者uccl_engine_write_vector()读写数据,返回当前的 transfer_id 写到nixlUcclReqH
checkXfer()
双边
从nixlUcclReqH 拿出当前要等的 transfer id, 调用uccl_engine_xfer_status 去轮询,如果需要 notif 的话就要多一个 uccl_engine_send_notify
releaseReqH()\
getNotifs()uccl_engine_get_notifs(),把 uccl 的完成翻译 给nixl
genNotif()独立的函数,调用 uccl_engine_send_notif

3. UCCL 与 Flagcx 不同之处

uccl 现在的 post 内 NIXL_READ/NIXL_WRITE都是调用的自己uccl_engine_read_vector()和uccl_engine_write_vector()的单边数据传输。然后uccl notfy的控制面用的 tcp/oob/socket 都是双边控制

flagcx 内如果走双边数据面,那我们就得双边控制面。