已关闭
[Requirement|需求建议]: 实现集群通信性能检测功能 #249
淡青创建于 5月26日关闭于 7月22日
Leewis
5月27日 评论:
5月27日 评论:
@weixin_43429619 感谢参与社区的贡献共享,集群通信性能检测功能方案设计中。


Leewis
5月27日 评论:
5月27日 评论:
/assign @weixin_43429619


5月27日 将 weixin_43429619 设为负责人
6月1日 关联了pull request:feat: 添加集群通信测试RFC,#249
7月22日 关闭了 issue
7月22日 添加了label:resolved
7月22日 关联了pull request:[feat]添加集群通信监控工具
Thanks for sending an requirement! Please fill in the following template to help quickly solve your problem.
Backgroud(背景信息)
提出一种面向RoCE无损集群的分层分域最小代价网络探测方法,通过拓扑感知生成最小开销探测矩阵,结合RNIC硬件计数器与自适应异常判定,实现低开销、高精度的网络状态监测与链路级故障定位,为昇腾HCCL提供无侵入、可大规模部署的通信观测能力。
-解决的问题:
针对复杂网络拓扑的认知问题,设计了在Spine-Leaf、HammingMesh、3D-Torus等集群拓扑下,自动识别拓扑、和保证最少探测路径数的分层分域探测的功能。
针对网络监测指标获取问题,解决传统探测冗余高、链路不可识别、无法精准获取全链路时延 / 丢包率,缺少RNIC硬件计数器(CNP)分析能力的问题。
针对异常分析定位问题,解决静态阈值误报高、无法准确定位到链路级根因的问题。
针对大规模集群的适应问题,解决大规模集群下单主机/单卡探测压力过大、全链路信息收敛慢、监控系统可扩展性不足的问题。
Origin(信息来源)
2012中央硬件研究院,计算网络技术部
Benefit / Necessity (价值/作用)
在昇腾集群大规模分布式训练中,为AllReduce、RingAllReduce等集合通信提供实时网络质量监测。针对训练时延抖动、迭代速度变慢、吞吐突降、算力利用率不足、通信长尾等性能衰减问题,实现网络层快速定位。
面向RoCE网络,对链路闪断、拥塞、交换机丢包、NPU丢包等异常进行检测与定位。解决无法识别慢故障、故障定位不准等问题。
Design(设计方案)
1. 总体架构
架构设计分两层:
控制层为中控设备,用户直接操作。设置ranktable、拓扑发现、编排pinglist、数据聚合、异常诊断(可独立运行)等模块。Host层控制device执行探测、数据上传。依赖hcomm基本通信原语,并行多对多探测。模块设计
网络监控应先进行拓扑发现,之后支持反复地网络探测。
代码文件结构
源代码交互关系
控制器
src/probe_controller.cpp通过proxy_call()请求 Host 进程、并且在控制器侧拿到返回值。util/tool/中定义的操作函数:定义了RNIC行为,由Host进程里的 rpc_server 根据绑定关系调用。util/topo/中的操作函数:定义了维护逻辑拓扑、Pinglist设计、任务下发、结果收集、分析与异常定位等功能,是控制器核心功能的实现代码。(注:灰色部分为操作函数的子函数)
2. 接口设计
ControlTopo 控制拓扑管理
控制层支持从 JSON 文件路径加载网络逻辑拓扑,是探测流程的入口,包含端侧节点信息。
// util/topo/control_topo.h:129-160 explicit ControlTopo(const json &j); explicit ControlTopo(const std::string &json_path);路由查询功能。
route_to_device()查找设备ID或IP,用于探测根节点到目标设备的完整路由路径。get_leaf_index()提供叶子节点到索引映射,用于数组访问。// util/topo/control_topo.h:167-168 std::vector<std::string> route_to_device(const std::string &device_id_or_ip) const; int get_leaf_index(const std::string &device_id_or_ip) const; void set_controller_ip(std::string controller_ip);leaf_list直接暴露所有叶子节点。叶子节点即实际探测节点。上层调用者可方便遍历所有探测节点。无需每次查询。// util/topo/control_topo.h:38 std::vector<std::string> leaf_list;MeshTopo 物理拓扑表示
存储Tracert发现的Mesh树状结构。记录各Mesh的父子关系、链路信息。
// util/topo/mesh_topo.h:46-49 MeshTopo() = default; MeshTopo(const ControlTopo &control_topo); MeshTopo(const json &j); MeshTopo(const std::string &json_path);JSON序列化/反序列化。用于添加/获取Mesh、Mesh的叶子节点、获取父Mesh。
// util/topo/mesh_topo.h:52-66 static MeshTopo from_json(const json &j); static MeshTopo from_json(const std::string &json_path); json to_json() const; void to_json(const std::string &json_path); void add_mesh(const Mesh &mesh); Mesh &get_mesh(const std::string &mesh_name); static std::string get_mesh_name(int level, int index); static int parse_mesh_name(const std::string &mesh_name); std::vector<std::string> get_leaf_kids(const Mesh &mesh) const; std::vector<std::string> get_leaf_kids(const std::string &mesh_name) const; void add_kid(const std::string &mesh_name, const std::string &kid_name); std::string get_mesh_father(const std::string &mesh_name) const;mesh_map存储所有Mesh。mesh_father记录 Mesh 父子关系。root_mesh记录根节点名称。// util/topo/mesh_topo.h:40-42 std::map<std::string, Mesh> mesh_map; std::map<std::string, std::string> mesh_father; std::string root_mesh;ProbeHelper 探测流程协调
核心协调器。串联拓扑发现、PingList 生成、链路测量、结果求解。
ProbeHelper接受五个参数:ControlTopo指针、四个RPC回调函数。get_tracert_ip_parallel获取网卡 IP。tracert_ports_muti_parallel并行Tracert。pinglist_insert_muti_parallel插入 PingList。ud_pingpong_tx_muti_parallel节点上批量PingPong。// util/helper/probe_helper.h:59-64 ProbeHelper( ControlTopo *ct, std::function<std::vector<std::string>(const std::vector<std::string> &)> get_tracert_ip_parallel, std::function<std::vector<std::vector<std::vector<std::vector<std::string>>>>(const std::vector<std::string> &, const std::vector<std::vector<std::string>> &, const std::vector<std::vector<int>> &)> tracert_ports_muti_parallel, std::function<void(const std::vector<std::string> &, const std::vector<std::vector<std::string>> &, const std::vector<std::vector<int>> &, const std::vector<std::vector<int>> &, const std::vector<int> &)> pinglist_insert_muti_parallel, std::function<std::vector<std::vector<std::vector<uint64_t>>>(const std::vector<std::string> &, const std::vector<int> &)> ud_pingpong_tx_muti_parallel);probe_topo()执行拓扑发现。get_pinglist()获取测量任务。set_pinglist()下发测量任务。get_pingpong_res()获取 PingPong 结果。solve_pingpong_res()求解链路时延。// util/helper/probe_helper.h:83-95 // 探测拓扑,初始化类里的所有私有变量 MeshTopo &probe_topo(); void set_mesh_topo(const MeshTopo &meshTopo); void set_mesh_topo(const json &j); void set_mesh_topo(const std::string &json_path); void set_mesh_topo(MeshTopo &meshTopo); // 获取pinglist:map<mesh_name, task<from, to, portnum>> std::map<std::string, std::vector<std::tuple<std::string, std::string, int>>> &get_pinglist(); // 设置pinglist到每个节点上 void set_pinglist(const std::map<std::string, std::vector<std::tuple<std::string, std::string, int>>> pinglist); // 获取tracert结果res:muti_device<tasks<res_vec<uint64_t>>> std::vector<std::vector<std::vector<u_int64_t>>> get_pingpong_res(int times = 1); // 求解结果res:link_global_id->link_res std::vector<float> solve_pingpong_res(const std::vector<std::vector<float>> &pingpong_res, const std::map<std::string, std::vector<std::tuple<std::string, std::string, int>>> &pinglist);Device 探测逻辑
Host层是端侧探测执行层。Host监听RPC请求,执行探测命令并上传结果。
完整任务链为:初始化服务 -> 启动服务监听 -> 接收控制层下发的探测任务 -> 执行Pingpong探测/执行ethtool命令-> 返回探测结果。
// util/tool/cmd/exec_cmd.h // util/tool/tracert/tracert.h HostResult HostInit(uint32_t port, uint32_t maxConnections); //初始化 Host 服务 HostResult HostDeinit(); // 释放Host进程 HostResult HostStart(); // 启动服务监听 HostResult HostStop(); // 停止服务监听 HostResult HostExecCmd(const char *cmd, char *output, size_t outputSize, int32_t *exitCode); // 执行Shell命令 HostResult HostGetNicIp(int32_t index, char *ip, size_t ipSize); // 获取网卡IP HostResult HostPingpongMuti(int32_t index, const char *dstIp, int32_t port, char path[128][64], int32_t *pathLen);3. 数据结构
disp_probe使用 JSON 配置文件描述控制拓扑和访问信息。模板:
{ "default_ssh_port": 22, "host_to_user_pair": { "ip": { "user": "<password>" } }, "control_topo": { "<node_id>": ["<node_id>", "<node_id>"] }, "to_path": "~/disp_probe", "from_path": "." }示例:
{ "default_ssh_port": 22, "host_to_user_pair": { "10.90.15.67": {"root": "HCCL@Helper2023"}, "10.90.15.69": {"root": "HCCL@Helper2023"} }, "control_topo": { "10.90.15.67": ["1-2", "4", "6-7"], "10.90.15.69": "0-7" }, "controller": {"10.90.15.67": ""}, "to_path": "~/xdu_test/disp_probe", "from_path": "." }字段说明:
default_ssh_porthost_to_user_paircontrol_topoto_pathfrom_path注意:
control_topo的值支持两种格式:["1-2", "4", "6-7"]- 混合范围和单个节点"0-7"- 范围表示,会自动展开成连续的节点 IDHost层定义了探测数据输入输出的数据结构,用于网卡 IP 获取、Shell 命令执行、Tracert 路径探测等网络探测功能的参数传递。// 初始化配置 typedef struct HostInitConfig { uint32_t port; // 监听端口 uint32_t maxConnections; // 最大并发连接数 } HostInitConfig; // 命令执行输入 typedef struct HostCmdInput { char cmd[4096]; // Shell 命令 } HostCmdInput; // 命令执行输出 typedef struct HostCmdOutput { char output[8192]; // 标准输出 int32_t exitCode; // 退出码 } HostCmdOutput; // Pingpong输入 typedef struct HostPingpongInput { int32_t index; // 网卡索引 char dstIp[64]; // 目标 IP int32_t port; // 目标端口 } HostTracertInput; // Pingpong输出 typedef struct HostPingpongOutput { char res[128][64]; // 探测延迟/丢包 } HostTracertOutput; // IP获取输入 typedef struct HostGetIpInput { int32_t index; // 网卡索引 } HostGetIpInput; // IP获取输出 typedef struct HostGetIpOutput { char ip[64]; // 网卡 IP } HostGetIpOutput;4. 关键逻辑
最小开销探测
探测计划不能简单增加probe数量,需要确保求解过程中链路可分辨。控制层用少量路径测量恢复可用的拓扑骨架,这一点区别于全量探测。随后只在已经识别出的局部拓扑展开完整探测。
Failleaper采用如下探测策略:
gen_topo():先对相邻节点进行少量 Tracert 探测,识别网络层级和Mesh拓扑结构。mesh_full_trace():在每个识别出的 Mesh 区域内部,对其叶子节点进行全网格探测,以获取链路信息。gen_pinglist():基于识别出的拓扑,只在必要的链路上生成探测任务,大幅减少探测。链路时延/丢包率求解
分析器基于路径结果反推链路(网络中直连的两个设备之间的链路)延迟/丢包。输入是路径级测量值,输出是链路级测量值。
求解按 Mesh 分块进行。已经求出的链路值会先从后续观测中扣除,只把剩余未知链路放进当前局部方程组。
solve_equation()使用Eigen的BDCSVD计算最小二乘解。自适应快速故障定位算法-时空交叉分析
主动监测收集关键网络信号后,应用Z-score分析来比较链路和节点随时间的延迟以及拓扑层的延迟。