| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
[refractor] NodeManager代码微重构,提升代码可维护性 Co-authored-by: 吕有辉<lvyouhui@huawei.com> # message auto-generated for no-merge-commit merge: !620 merge refractor/node_manager into master [refractor] NodeManager代码微重构,提升代码可维护性 Created-by: codeDogPro Commit-by: 吕有辉 Merged-by: tobking Description: ## 1. 合入背景 ISSUE:https://gitcode.com/Ascend/MindIE-Motor/issues/368 ## 2. 修改内容 ### 2.1 Service Registry 重构 **文件**: motor/node_manager/core/services/registry.py 1. 用 typing.cast 消除 get_preparable() 中的 # type: ignore[arg-type,return-value]。 2. _MODULE_MAP 从模块级静态 dict 迁移到 _ServiceRegistry 实例属性,新增 add_discovery_path() API 支持动态注册后端模块路径。 3. 新增 get_active_sorted() 方法,将排序逻辑从 daemon.py 内联哨兵模式收归 registry。 4. _ServiceRegistration.is_active 改为 _is_active(active_backends) 方法,接受解析后的后端列表参数。 5. discover() 支持逗号分隔的多后端服务列表(如 "engine,memcache"),替代原来的单值匹配。 6. 删除 __slots__ 限制,2-3 个实例的内存节省可忽略。 7. 新增 tests/node_manager/core/services/test_registry.py,20 个单元测试覆盖 register、get_active 过滤、get_preparable 排序、discover 模块导入、重复注册、add_discovery_path、线程安全。 ### 2.2 服务协议提取 **文件**: motor/node_manager/core/services/protocols.py(新增) 1. DaemonService 和 PreparableService 从 registry.py 提取到 services/protocols.py。 2. daemon.py 直接从 protocols.py 导入,Protocol 定义与注册中心解耦。 ### 2.3 memcache LocalService 重构 **文件**: motor/node_manager/core/services/memcache/(新增目录) 1. **目录拆分**: services/memcache/ __init__.py worker.py ← LocalService 子进程入口(DistributedObjectStore().init(0)) lifecycle.py ← daemon 侧生命周期管理(@register_service、pull/stop/health_check) 2. **拉起方式改进**:pull() 使用 sys.executable -m motor.node_manager.core.services.memcache.worker 替代内联 -c 字符串,取消 PYTHON_EXEC_PATH 依赖。保持 subprocess.Popen(env=...) 确保与 Engine 子进程的 MMC_LOCAL_CONFIG_PATH 隔离。 3. **消除重复检查**:提取 _can_launch property,统一 should_launch() / pull() / prepare() 中的 enable、backend、mode 条件判断。 4. **简化 mark_dead()**:用 poll() 替代 wait(timeout=0) + 三重异常捕获。 5. **移除未使用的 _endpoints_count**:仅在日志中使用,改为局部变量。 ### 2.4 Engine 解耦 —— 服务配置化 **文件**: motor/node_manager/core/services/engine.py, motor/node_manager/core/daemon.py, motor/node_manager/main.py, motor/config/node_manager.py 1. @register_service(SERVICE_ENGINE) 新增 backend="engine",从 backend=None(始终激活)改为按配置激活。 2. KVCacheStoreConfig 新增 mode 字段("combined" / "separated"),通过 user_config.json 控制: json // Engine + KV 合体 Pod(默认) { "kv_cache_store_config": { "backend": "memcache", "mode": "combined" } } // KV 分离 Pod(只起 LocalService,不拉 Engine,不注册/心跳) { "kv_cache_store_config": { "backend": "memcache", "mode": "separated" } } // Engine only Pod {} 3. Daemon 新增 has_engine 属性,main.py 据此条件初始化 EngineManager / HeartbeatManager。 ### 2.5 main.py 重构 —— Application 基类 **文件**: motor/common/app/application.py(新增), motor/node_manager/node_manager.py(新增), motor/node_manager/main.py 1. **Application 基类** — 封装四个组件共享的 boilerplate: - 模块管理(add_module / get_module / stop_all_modules) - 配置热更新传播(on_config_updated → 先刷新自身间隔 _refresh_check_interval,再传播给所有带 update_config 的模块) - 可配置的 daemon loop 间隔(check_interval 参数,默认 1s,子类从 config 读取) - 信号处理(SIGINT / SIGTERM → threading.Event) - select-based daemon loop(stdin 读取 + stop_event.wait) - run() 模板方法:banner → init_modules → start_modules → config_watcher → daemon_loop → shutdown 2. **NodeManager(Application)**: - __init__ 传入 check_interval=config.basic_config.daemon_loop_interval(默认 5s,可在 user_config.json 中配置) - _refresh_check_interval():配置热更新时同步刷新间隔 - init_modules():根据 daemon.has_engine 动态注册模块 - _on_daemon_tick():每 tick 检查 HeartbeatManager 自杀标志 - exit_code:自杀时返回 -1(pod rescheduling) 3. **main.py 瘦身**:从 186 行 → 37 行 thin wrapper: python def main() -> int: config = NodeManagerConfig.from_json() reconfigure_logging(config.logging_config) run_port_setup_or_exit(apply_node_manager_ports, config) nm = NodeManager(config) return nm.run() 删除所有模块级全局变量(modules、_should_exit、config、config_watcher)和 7 个模块级函数。 ### 2.6 测试重构 1. 测试目录镜像源码结构: tests/node_manager/ __init__.py conftest.py test_config.py core/ __init__.py test_daemon.py test_engine_manager.py test_heartbeat_manager.py test_fault_reporter.py test_api_ready_event.py services/ __init__.py test_registry.py memcache/ __init__.py test_lifecycle.py 2. test_main_process_title.py 从 NodeManager 和 EngineServer 各一份合并为 tests/common/utils/test_process_title.py,NodeManager 用例适配新 NodeManager 类 API。 ### 2.7 改动文件清单 | 文件 | 改动类型 | |------|----------| | motor/common/app/__init__.py | 新增 | | motor/common/app/application.py | 新增 | | motor/node_manager/node_manager.py | 新增 | | motor/node_manager/core/services/protocols.py | 新增 | | motor/node_manager/core/services/memcache/__init__.py | 新增 | | motor/node_manager/core/services/memcache/worker.py | 新增 | | motor/node_manager/core/services/memcache/lifecycle.py | 重命名自 local_service.py | | tests/node_manager/core/__init__.py | 新增 | | tests/node_manager/core/services/__init__.py | 新增 | | tests/node_manager/core/services/memcache/__init__.py | 新增 | | tests/node_manager/core/services/test_registry.py | 新增 | | tests/node_manager/core/services/memcache/test_lifecycle.py | 重命名 | | tests/common/utils/test_process_title.py | 合并自两份拷贝 | | motor/node_manager/core/services/registry.py | 重构 | | motor/node_manager/core/daemon.py | 重构 | | motor/node_manager/core/services/engine.py | 改动 | | motor/node_manager/main.py | 瘦身 | | motor/config/node_manager.py | 改动 | | motor/node_manager/core/__init__.py | 删除多余版权声明 | | motor/node_manager/core/services/__init__.py | 删除多余版权声明 | | motor/node_manager/__init__.py | 删除多余版权声明 | ## 3. 资料变更 不涉及。 ## 4. 接口变更 不涉及(所有改动为内部重构,对外接口不变)。 ## 5. 测试结果 python -m pytest tests/node_manager/ tests/common/utils/test_process_title.py tests/engine_server/ -q 529 passed in 1.47s 测试覆盖: - **registry**:注册、过滤、排序、发现、线程安全(20 个用例) - **memcache lifecycle**:should_launch、prepare、pull、stop、health_check(11 个用例) - **daemon**:engine pull、参数校验、D2D peer、signal handler(13 个用例) - **heartbeat manager**:状态上报、端点管理、自杀检测 - **engine manager**:注册、re-register、ranktable、snapshot - **config**:配置解析、验证、热加载 - **process_title**:NodeManager + EngineServer 标题设置(4 个用例) ## 6. CheckList - [x] 代码注释完备 - [x] 正确记录维测日志 - [x] 是否有UT用例(新增 24 个用例,全量 529 passed) - [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 - _ServiceRegistry 使用 threading.Lock 保护 _registrations 和 _module_map - daemon.py 和 engine.py 的锁均为短临界区非嵌套使用 - Application 的信号处理仅设 threading.Event,清理在主线程执行 See merge request: Ascend/MindIE-Motor!620 | 9 天前 | |
[feature]增加Mooncake Conductor故障恢复的RAS能力 Co-authored-by: zhoujing101<zhoujing101@huawei.com> # message auto-generated for no-merge-commit merge: !337 merge master into master [feature]增加Mooncake Conductor故障恢复的RAS能力 Created-by: zhoujing101 Commit-by: zhoujing101 Merged-by: towncharlie Description: ## **1. 合入背景** Mooncake Conductor缺少RAS能力,发生故障重启后,无法正常重新工作。 需要增加重注册能力,依赖mooncake社区PR( https://github.com/kvcache-ai/Mooncake/pull/2595 ) 合入后提供查询已注册实例信息接口。 [#212](https://gitcode.com/Ascend/MindIE-PyMotor/issues/212) ## **2. 修改内容** 开启kv cache亲和性调度时,每隔30秒(可配置,配置为0则不重注册)会去conductor获取一次实例列表(依赖PR: https://github.com/kvcache-ai/Mooncake/pull/2595 ),对比差异,将缺少的实例补注册到Condutor。 ## **3. 资料变更** “不涉及”。 ## **4. 接口变更** “不涉及”。 ## **5. 测试结果** 正常情况:  当mooncake conductor发生重启时:  ## **6. CheckList** > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 --- # 测试用例总结 ## 1. tests/config/test_config_utils.py — 配置解析(9 个用例) ### TestResolveReRegisterIntervalSec | 测试方法 | 覆盖场景 | 预期结果 | |---|---|---| | test_returns_default_when_motor_coordinator_missing | 顶层 motor_coordinator_config 键缺失 | 返回 DEFAULT_RE_REGISTER_INTERVAL_SEC (30) | | test_returns_default_when_motor_coordinator_not_dict | motor_coordinator_config 值不是 dict | 返回默认值 30 | | test_returns_default_when_prefill_kv_event_config_missing | motor_coordinator 存在但缺少 prefill_kv_event_config | 返回默认值 30 | | test_returns_default_when_prefill_kv_event_config_not_dict | prefill_kv_event_config 存在但不是 dict | 返回默认值 30 | | test_returns_default_when_re_register_interval_missing | prefill_kv_event_config 中缺少 re_register_interval_sec | 返回默认值 30 | | test_returns_default_when_re_register_interval_is_none | re_register_interval_sec 显式设为 None | 返回默认值 30 | | test_returns_configured_value | 正常传入 120 | 返回 int 120 | | test_accepts_string_value | 传入字符串 "45" | 返回 int 45 | | test_accepts_zero | 传入 0(禁用定时器) | 返回 int 0 | --- ## 2. tests/coordinator/api_client/test_conductor_api_client.py — Conductor API 客户端(28 个用例) ### TestConductorInstanceId(4 个) | 测试方法 | 覆盖场景 | 预期结果 | |---|---|---| | test_role_u_returns_union_prefix | ROLE_U 实例 | conductor_instance_id() 返回 "vllm-union-7" | | test_role_p_returns_prefill_prefix | ROLE_P 实例 | conductor_instance_id() 返回 "vllm-prefill-3" | | test_role_e_falls_to_prefill_prefix | ROLE_E 实例(非 U 回退) | conductor_instance_id() 返回 "vllm-prefill-5" | | test_role_d_falls_to_prefill_prefix | ROLE_D 实例(非 U 回退) | conductor_instance_id() 返回 "vllm-prefill-9" | ### TestBuildRegisterPayload(5 个) | 测试方法 | 覆盖场景 | 预期结果 | |---|---|---| | test_returns_empty_dict_when_endpoint_format_invalid | endpoint 没有 *: 分隔符 | 返回空 dict {} | | test_basic_payload_without_replay | 标准 payload,无 replay_endpoint | 返回含 endpoint/type/modelname/block_size/instance_id/dp_rank 的 dict | | test_payload_with_replay_endpoint | 带 replay_endpoint 配置 | payload 包含 replay_endpoint 字段,端口为 base + endpoint.id | | test_payload_dp_rank_uses_endpoint_id | dp_rank 取自 endpoint.id(非 0) | dp_rank == 5,endpoint 端口为 5557 + 5 = 5562 | | test_replay_endpoint_format_invalid_no_star_colon | replay_endpoint 没有 *: 分隔符 | payload 中**不包含** replay_endpoint 键 | ### TestNormalizeServiceKey(9 个) | 测试方法 | 覆盖场景 | 预期结果 | |---|---|---| | test_all_uppercase_keys | Conductor 返回大写 key | 正确提取四个字段值 | | test_lowercase_keys_not_found_by_uppercase_lookup | 只有小写 key(大写 key 不存在) | 全部返回默认值 ("", -1, "", "") | | test_dp_rank_zero | dp_rank=0被正确解析 | dp_rank == 0 | | test_dp_rank_missing_defaults_to_minus_one | DPRank 完全缺失 | 默认 -1 | | test_dp_rank_non_numeric_string_returns_minus_one | DPRank 为非数值字符串 "abc" | 返回 -1 | | test_dp_rank_empty_string_returns_minus_one | DPRank 为空字符串 "" | 返回 -1(isdigit=False) | | test_instance_id_empty_when_missing | InstanceID 缺失 | instance_id == "" | | test_endpoint_empty_when_missing | Endpoint 缺失 | endpoint == "" | | test_replay_endpoint_empty_when_missing | ReplayEndpoint 缺失 | replay_endpoint == "" | | test_instance_id_empty_when_missing | InstanceID 缺失 | instance_id == "" | | test_endpoint_empty_when_missing | Endpoint 缺失 | endpoint == "" | | test_replay_endpoint_empty_when_missing | ReplayEndpoint 缺失 | replay_endpoint == "" | ### TestGetRegisteredServices(4 个) | 测试方法 | 覆盖场景 | 预期结果 | |---|---|---| | test_returns_services_list | Conductor /services 正常返回 | 返回 services 列表 | | test_returns_empty_when_response_not_dict | 响应不是 dict | 返回空列表 [] | | test_returns_empty_when_services_not_list | services 字段不是 list | 返回空列表 [] | | test_raises_on_http_error | HTTP 请求异常 | 向上抛出原始异常 | ### TestReRegisterKvInstances(6 个) | 测试方法 | 覆盖场景 | 预期结果 | |---|---|---| | test_skip_when_no_registered_services | get_registered_services() 抛出异常(Conductor 不可用) | 跳过,register_post 不被调用 | | test_skip_non_kva_roles | ROLE_D / ROLE_E 不在 _KVA_ROLES 中 | register_post 不被调用 | | test_skip_when_payload_empty | _build_register_payload() 返回空 dict | register_post 不被调用 | | test_re_registers_when_service_missing | 本地实例在 Conductor 中不存在 | register_post 被调用一次 | | test_skips_when_already_registered | 实例已在 Conductor 中注册(所有字段匹配) | register_post **不**被调用 | | test_re_registers_only_missing_among_multiple | 多个 endpoint,仅 dp_rank=1 缺失 | register_post 仅被调用一次(ep_id=1) | --- ## 覆盖率统计 | 模块 | 覆盖函数/方法 | |---|---| | motor.config.config_utils._resolve_re_register_interval_sec | 全部 9 条分支 | | motor.coordinator.api_client.conductor_api_client.conductor_instance_id | 2 条分支(U / 非 U) | | ConductorApiClient._build_register_payload | endpoint 格式、replay 有无、replay 格式 | | ConductorApiClient._normalize_service_key | 大写/小写 key、dp_rank=0 边界、字段缺失默认值、非数值字符串、空字符串 | | ConductorApiClient.get_registered_services | 正常/格式错误/异常 | | ConductorApiClient.re_register_kv_instances | Conductor 不可用、非 KVA 跳过、payload 为空、新注册、已注册跳过、部分缺失 | See merge request: Ascend/MindIE-PyMotor!337 | 1 个月前 | |
[feature] 支持 Prefill 跨机 Pipeline Parallel 拉起 Co-authored-by: Jechin<yuzechen1@huawei.com> # message auto-generated for no-merge-commit merge: !653 merge feature/prefill-cross-node-pp into master [feature] 支持 Prefill 跨机 Pipeline Parallel 拉起 Created-by: Jechin Commit-by: Jechin Merged-by: towncharlie Description: ## **1. 合入背景** Fixes [#389](https://gitcode.com/Ascend/MindIE-Motor/issues/389) Prefill 跨机 Pipeline Parallel(如 TP=16、PP=2、nnodes=2)场景下,控制面仍按“单机并行积”计算 local_world_size(pcp×tp×pp),导致本机设备数校验失败、Endpoint 为空;同时 master_addr=placeholder / 静态 node_rank 会盖住运行时注入,分布式初始化无法连通。Assembler 在无 Endpoint 时还会误报 start 成功。本 PR 补齐跨机 PP 与跨机 PCP 共用的 nnodes 路径,并让 Deployer 从 vLLM 脚本正确生成 PP/nnodes 配置;并行度读取统一为 CLI 整数优先、缺省回退 kv_connector_extra_config(含 pp_size)。 ## **2. 修改内容** 1. **NodeManager 配置**(motor/config/node_manager.py) - 跨机时按 (pcp×tp×pp)//nnodes 折算本机 local_world_size(覆盖 PP/PCP) - pcp×pp 不能被 nnodes 整除时直接报错,避免错误拓扑静默通过 2. **EngineServer VLLMConfig**(motor/engine_server/core/vllm/vllm_config.py) - 跨机场景强制覆盖 master_addr / node_rank / headless,不再被 placeholder 挡住 - Mooncake kv extra 合并并行度时保留用户字段(如 pp_layer_partition) 3. **Controller InstanceAssembler**(motor/controller/core/instance_assembler.py) - 所有 NodeManager 均无 Endpoint 时,_send_start_command 返回失败并打 ERROR,禁止假成功 4. **Deployer 转换**(examples/deployer/config_tool/vllm_to_motor.py) - 保留并正确写出 pipeline_parallel_size,按 tp×pp 推导 Pod / nnodes - 跨机时写入 nnodes / master-port;不写 master-addr / node-rank(运行时注入) - **dp/tp/pp 统一读取优先级**:命令行给了正整数用 CLI,否则回退 kv_connector_extra_config 的 dp_size / tp_size / pp_size(kv 中的 size 在写出前剥离) - 去除硬件侧强制 remap tp/dp;infer_*_motor_deploy_config 回传 nnodes,与跨机 engine 注入共用一次 _infer_pod_layout - 抽取 hybrid 默认 deploy / 权重挂载路径 / preset+cards 等重复逻辑,降低漂移风险 5. **UT** - 覆盖 PP 折算、不可整除、placeholder 覆盖、kv 字段保留、空 Endpoint start 失败 - Deployer:CLI>kv、仅 kv 回退(含 pp_size)、跨机 nnodes/master-port、跳过脚本透传多机键等 **进程视图** mermaid flowchart LR subgraph deploy [Deploy] script["vLLM serve 脚本\nCLI 与 kv extra"] conv["vllm_to_motor\nCLI大于kv"] uc["user_config\nPP nnodes master-port"] end subgraph control [Control Plane] nm0["NodeManager node_rank=0"] nm1["NodeManager node_rank=1"] asm["InstanceAssembler"] end subgraph engine [Engine] es0["EngineServer PP stage0"] es1["EngineServer PP stage1 headless"] end script --> conv --> uc uc --> nm0 uc --> nm1 nm0 -->|"Register local_world_size"| asm nm1 -->|"Register local_world_size"| asm asm -->|"StartCmd master_dp_ip/node_rank"| nm0 asm -->|"StartCmd"| nm1 nm0 --> es0 nm1 --> es1 es0 <-->|"master-port rendezvous"| es1 ## **3. 资料变更** 不涉及仓库内用户文档更新(Deployer README / 跨机说明未改)。 ## **4. 接口变更** 涉及配置约定(客户面可见): - Prefill 跨机 PP 需配置 pipeline_parallel_size、nnodes、master-port;**不要**配置 master-addr / node-rank - Deployer 从 vLLM 脚本转换时会自动生成上述项;pipeline_parallel_size 不再被强制改写为 1 - Deployer 并行度语义:--data/tensor/pipeline-parallel-size 正整数优先于 kv extra 的 dp_size/tp_size/pp_size;二者皆无时 dp/tp 走手动占位提示,pp 缺省为 1 - 无新增/变更 HTTP API ## **5. 测试结果** (自行补充) ## **6. CheckList** [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!653 | 1 天前 | |
【bugfix】coordinator add weight config Co-authored-by: ganglv<lvgang1@huawei.com> # message auto-generated for no-merge-commit merge: !677 merge master_icbc_shanghai into master 【bugfix】coordinator add weight config Created-by: ganglv Commit-by: ganglv Merged-by: tobking Description: ## **1. 合入背景** > 请描述为什么要做这个PR内的改动。\ > 如涉及,请关联前序PR或同特性/需求下的其他PR。\ > 如果是修复之前PR引入的问题,请关联引入问题的PR。\ > 请通过#ISSUE ID关联issue。\ > 注意: Fixes #ISSUE ID会自动关闭issue,如问题部分解决请不要使用Fixes,可以用Fix part of #ISSUE ID替代. KV Cache 亲和调度此前用 Conductor 返回的 matched_tokens(按介质覆盖终点)直接参与打分,存在两点不足: 1. **npu/cpu/disk_blocks 语义不清**:重叠前缀下各介质块数可能重复计入,无法表达「互斥真实命中块数」。 2. **介质价值差异无法配置**:HBM/NPU、CPU、Disk 对 TTFT 的贡献不同,但调度侧无法按介质加权;权重属于调度策略,不宜放在 Conductor(事实层)。 本 PR 将职责拆清:Conductor 只上报互斥命中事实;Coordinator 按 w_npu/w_cpu/w_disk 做亲和加权,并顺带把亲和参数收敛到嵌套配置 scheduler_config.kv_affinity。 ## **2. 修改内容** > 请<ins>**描述修改内容的具体实现**</ins>,涉及哪些组件之间进行交互,可以用1、2、3、...进行罗列。 > 如果是需求或者重构类的PR,需要<ins>**补充详细设计文档**</ins>(说明上下游组件关系、时序图、类图、DFX能力等内容)。 1. **KV Conductor(事实层)** - 匹配阶段收集每 DP 的介质绝对终点(npu_end/cpu_end/disk_end)。 - build_response 按优先级 **NPU > CPU > Disk** 做互斥划分,写入 npu_blocks/cpu_blocks/disk_blocks。 - matched_tokens = (npu+cpu+disk) × block_size(未加权真实覆盖长度);实例级 longest_matched 仍取各 DP max。 2. **Coordinator(策略层)** - 新增/使用 KvAffinityConfig,配置迁入 scheduler_config.kv_affinity: - 原有:mode / load_weight / overlap_credit / prefill_load_scale / load_gate_topn - 新增:w_npu / w_cpu / w_disk(默认 **1.0 / 1.0 / 0.0**) - 亲和打分: text affinity_matched = min(round((npu×w_npu + cpu×w_cpu + disk×w_disk)×block_size), isl) prefill_cost = max(0, isl − overlap_credit × affinity_matched) - 兼容旧 flat key(kv_affinity_mode 等):自动迁入嵌套结构并告警;嵌套优先。 3. **配置透传** - scheduler_connection_manager / scheduler_client 将 kv_affinity 权重传入 KvCacheAffinityPolicy。 4. **文档与示例** - 更新亲和调度用户指南、配置参考、kv-conductor README/设计文档、config_sample.json 及 skill 文档。 ## **3. 资料变更** > 请确认<ins>**是否涉及资料变更**</ins>。\ > 如涉及,需要在PR中体现,并简要说明修改内容。\ > 如不涉及,需填写“不涉及”。 涉及。已更新: - docs/zh/user_guide/features/kvcache_affinity.md - docs/zh/user_guide/configuration/config_reference.md - docs/zh/user_guide/deployment/k8s/pd_aggregation_deployment.md - docs/zh/design/kv_conductor.md - motor/kv_conductor/README.md - examples/features/config_sample.json - .agent/skills/motor-dev/references/{kv-conductor,coordinator}.md ## **4. 接口变更** > 请确认<ins>**是否涉及跨代码仓或者客户面可见的接口变更**</ins>。\ > 如涉及,需详细说明接口以及对应的变更内容,同时需要在资料中体现。\ > 如不涉及,需填写“不涉及”。 涉及(客户面配置与 Conductor 响应语义): | 位置 | 变更 | |------|------| | Coordinator 配置 | 亲和参数由 flat kv_affinity_* 改为嵌套 scheduler_config.kv_affinity;保留 legacy 迁移 | | kv_affinity.w_npu/w_cpu/w_disk | 新增;默认 1.0/1.0/0.0 | | Conductor *_blocks | 语义改为互斥真实命中块数(NPU>CPU>Disk) | | Conductor matched_tokens | 改为互斥块数之和 × block_size(不再在 Conductor 侧乘权重) | ## **5. 测试结果** > 需体现<ins>**测试场景,测试方法以及测试结果**</ins>。\ > 测试用例设计时需考虑硬件、部署方式、功能、性能、精度、显存等维度。  ## **6. CheckList** > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] [ ] 代码注释完备 [ ] 正确记录维测日志 [ ] 是否有UT用例 [ ] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!677 | 1 天前 | |
[fix] 修复Coordinator实例管理无法过滤相同job_name实例的问题 Co-authored-by: 吕有辉<lvyouhui@huawei.com> # message auto-generated for no-merge-commit merge: !643 merge fix/coordinator_ins_mgmt into master [fix] 修复Coordinator实例管理无法过滤相同job_name实例的问题 Created-by: codeDogPro Commit-by: 吕有辉 Merged-by: towncharlie Description: ## **1. 合入背景** https://gitcode.com/Ascend/MindIE-Motor/issues/378 ## **2. 修改内容** instance_manager.py:427-470 中的 _add_instances 在添加实例时,仅按 instance.id 做去重检查(第 433 行检查 unavailable pool,_add_instance_to_available_pool 中检查 available pool)。当 Pod 重启后获得新的 instance.id 但保持相同的 job_name 时,旧实例(旧 ID)仍留在池中,新实例(新 ID)也被添加进来,导致同一个 job_name 对应两个不同 ID 的实例。 修复方案 新增两个私有辅助方法,并在 _add_instances 中添加 job_name 去重逻辑: 1. _find_instance_by_job_name (第 427-433 行) 遍历 available、unavailable、paused 三个池,按 job_name 查找已有实例。 2. _remove_instance_from_all_pools (第 435-447 行) 从任意池中移除指定 ID 的实例。对于 available pool,委托给 _delete_instance_from_available_pool 以正确处理角色子池、endpoint cache、workload lock 的清理。 3. _add_instances 中的去重守卫 (第 465-480 行) 在尝试添加新实例之前,先检查是否有相同 job_name 但不同 id 的旧实例存在。如果存在,先移除旧实例(日志级别为 WARNING 以引起注意),再添加新实例,确保池中不会出现同一 job_name 的两个实例。 新增测试用例: _find_instance_by_job_name (4 个) 测试 场景 test_find_instance_by_job_name_found_in_available_pool 在 available pool 中找到 test_find_instance_by_job_name_found_in_unavailable_pool 在 unavailable pool 中找到 test_find_instance_by_job_name_found_in_paused_pool 在 paused pool 中找到 test_find_instance_by_job_name_not_found 未找到返回 None _remove_instance_from_all_pools (4 个) 测试 场景 test_remove_instance_from_all_pools_from_available 从 available pool 移除(含角色子池清理) test_remove_instance_from_all_pools_from_unavailable 从 unavailable pool 移除 test_remove_instance_from_all_pools_from_paused 从 paused pool 移除 test_remove_instance_from_all_pools_not_found 不在任何池中返回 False _add_instances job_name 去重 (5 个) 测试 场景 test_add_instances_same_job_name_different_id_replaces_stale 核心场景:同 job_name 不同 ID(Pod 重启),旧实例被移除,新实例加入 test_add_instances_same_job_name_different_id_from_unavailable_pool 旧实例在 unavailable pool 中被替换 test_add_instances_same_job_name_different_id_from_paused_pool 旧实例在 paused pool 中被替换 test_add_instances_same_job_name_and_id_skips_as_duplicate 同 job_name 且同 ID → 保持原有重复 ID 检查行为 test_add_instances_same_job_name_multiple_new_instances 多个新实例(各自不同 job_name)正常添加,无交叉干扰 ## **3. 资料变更** 不涉及 ## **4. 接口变更** 不涉及 ## **5. 测试结果** 测试ok ## **6. CheckList** > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] [ ] 代码注释完备 [ ] 正确记录维测日志 [ ] 是否有UT用例 [ ] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!643 | 9 天前 | |
[feature] 支持 Prefill 跨机 Pipeline Parallel 拉起 Co-authored-by: Jechin<yuzechen1@huawei.com> # message auto-generated for no-merge-commit merge: !653 merge feature/prefill-cross-node-pp into master [feature] 支持 Prefill 跨机 Pipeline Parallel 拉起 Created-by: Jechin Commit-by: Jechin Merged-by: towncharlie Description: ## **1. 合入背景** Fixes [#389](https://gitcode.com/Ascend/MindIE-Motor/issues/389) Prefill 跨机 Pipeline Parallel(如 TP=16、PP=2、nnodes=2)场景下,控制面仍按“单机并行积”计算 local_world_size(pcp×tp×pp),导致本机设备数校验失败、Endpoint 为空;同时 master_addr=placeholder / 静态 node_rank 会盖住运行时注入,分布式初始化无法连通。Assembler 在无 Endpoint 时还会误报 start 成功。本 PR 补齐跨机 PP 与跨机 PCP 共用的 nnodes 路径,并让 Deployer 从 vLLM 脚本正确生成 PP/nnodes 配置;并行度读取统一为 CLI 整数优先、缺省回退 kv_connector_extra_config(含 pp_size)。 ## **2. 修改内容** 1. **NodeManager 配置**(motor/config/node_manager.py) - 跨机时按 (pcp×tp×pp)//nnodes 折算本机 local_world_size(覆盖 PP/PCP) - pcp×pp 不能被 nnodes 整除时直接报错,避免错误拓扑静默通过 2. **EngineServer VLLMConfig**(motor/engine_server/core/vllm/vllm_config.py) - 跨机场景强制覆盖 master_addr / node_rank / headless,不再被 placeholder 挡住 - Mooncake kv extra 合并并行度时保留用户字段(如 pp_layer_partition) 3. **Controller InstanceAssembler**(motor/controller/core/instance_assembler.py) - 所有 NodeManager 均无 Endpoint 时,_send_start_command 返回失败并打 ERROR,禁止假成功 4. **Deployer 转换**(examples/deployer/config_tool/vllm_to_motor.py) - 保留并正确写出 pipeline_parallel_size,按 tp×pp 推导 Pod / nnodes - 跨机时写入 nnodes / master-port;不写 master-addr / node-rank(运行时注入) - **dp/tp/pp 统一读取优先级**:命令行给了正整数用 CLI,否则回退 kv_connector_extra_config 的 dp_size / tp_size / pp_size(kv 中的 size 在写出前剥离) - 去除硬件侧强制 remap tp/dp;infer_*_motor_deploy_config 回传 nnodes,与跨机 engine 注入共用一次 _infer_pod_layout - 抽取 hybrid 默认 deploy / 权重挂载路径 / preset+cards 等重复逻辑,降低漂移风险 5. **UT** - 覆盖 PP 折算、不可整除、placeholder 覆盖、kv 字段保留、空 Endpoint start 失败 - Deployer:CLI>kv、仅 kv 回退(含 pp_size)、跨机 nnodes/master-port、跳过脚本透传多机键等 **进程视图** mermaid flowchart LR subgraph deploy [Deploy] script["vLLM serve 脚本\nCLI 与 kv extra"] conv["vllm_to_motor\nCLI大于kv"] uc["user_config\nPP nnodes master-port"] end subgraph control [Control Plane] nm0["NodeManager node_rank=0"] nm1["NodeManager node_rank=1"] asm["InstanceAssembler"] end subgraph engine [Engine] es0["EngineServer PP stage0"] es1["EngineServer PP stage1 headless"] end script --> conv --> uc uc --> nm0 uc --> nm1 nm0 -->|"Register local_world_size"| asm nm1 -->|"Register local_world_size"| asm asm -->|"StartCmd master_dp_ip/node_rank"| nm0 asm -->|"StartCmd"| nm1 nm0 --> es0 nm1 --> es1 es0 <-->|"master-port rendezvous"| es1 ## **3. 资料变更** 不涉及仓库内用户文档更新(Deployer README / 跨机说明未改)。 ## **4. 接口变更** 涉及配置约定(客户面可见): - Prefill 跨机 PP 需配置 pipeline_parallel_size、nnodes、master-port;**不要**配置 master-addr / node-rank - Deployer 从 vLLM 脚本转换时会自动生成上述项;pipeline_parallel_size 不再被强制改写为 1 - Deployer 并行度语义:--data/tensor/pipeline-parallel-size 正整数优先于 kv extra 的 dp_size/tp_size/pp_size;二者皆无时 dp/tp 走手动占位提示,pp 缺省为 1 - 无新增/变更 HTTP API ## **5. 测试结果** (自行补充) ## **6. CheckList** [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!653 | 1 天前 | |
fix: multi_deployment 静态扩缩容基于集群 index 动态 list 统一扩缩容决策 Co-authored-by: lbr711<liuboru1@huawei.com> # message auto-generated for no-merge-commit merge: !686 merge pr/fix-static-scale into master fix: multi_deployment 静态扩缩容基于集群 index 动态 list 统一扩缩容决策 Created-by: lbr711 Commit-by: lbr711 Merged-by: towncharlie Description: ## **1. 合入背景** > multi_deployment 静态扩缩容原先扩/缩不对称:扩容部分看集群,缩容仍按配置 reversed(range(base)) 推断,Pending 场景会误删健康实例;稀疏 index 下扩容无法补洞、缩容可能删不到实际 Deployment。 > > 本 PR 以**集群实际 Deployment index 集合**为动态 list,统一 P/D/U 扩缩容 index 选择逻辑。 > > Fixes #454 ## **2. 修改内容** 1. 新增 get_pending_engine_instance_indices():查询 Pending Pod 对应 index(无 idx < base 限制)。 2. 新增 compute_scale_in_delete_indices() / compute_scale_out_add_indices():纯函数,基于 live index set 计算删/增列表。 3. 重构 get_instance_scale_in_delete_order():删除数量 = len(现有) - target;删序 Pending 优先 → 高位优先;deployment 查询失败回退 reversed(range(base))。 4. 重构 get_instance_scale_out_indices():在 [0, total) 内从低到高补缺失 index。 5. scale_engine_by_type() 中 P/D/U 接入上述逻辑;E 保持原有行为。 6. 扩展 UT tests/examples/deployer/test_scale_in.py(含稀疏 index 全链路、orphan 高位回收等场景)。 ## **3. 资料变更** 不涉及。 ## **4. 接口变更** 不涉及。 ## **5. 测试结果** - 部署方式:multi_deployment - 测试方法:pytest 单元测试 - 测试场景: 1. Pending 优先于 Running 删除(P/D/U) 2. 无 Pending 时高位优先删除 3. 稀疏 index 扩容补洞(如 {0,4} → 补 index 1) 4. 稀疏 index 缩容回收 orphan 高位(如 {0,1,4} 3→2 删 index 4) 5. 全链路:5→2 Pending 删洞 → 2→3 补位 → 3→2 正常缩容 6. deployment 查询失败回退旧逻辑 - 测试结果:21/21 passed(test_scale_in.py) bash pytest tests/examples/deployer/test_scale_in.py -v ## **6. CheckList** [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!686 | 7 小时前 | |
Revert "[feature] get rid of ranktable" Co-authored-by: lbr711<liuboru1@huawei.com> # message auto-generated for no-merge-commit merge: !218 merge revert_ranktable into master Revert "[feature] get rid of ranktable" Created-by: lbr711 Commit-by: lbr711 Merged-by: towncharlie Description: ## **1. 合入背景** > 请描述为什么要做这个PR内的改动。\ > 如涉及,请关联前序PR或同特性/需求下的其他PR。\ > 如果是修复之前PR引入的问题,请关联引入问题的PR。\ > 请通过#ISSUE ID关联issue。\ > 注意: Fixes #ISSUE ID会自动关闭issue,如问题部分解决请不要使用Fixes,可以用Fix part of #ISSUE ID替代. ## **2. 修改内容** > 请<ins>**描述修改内容的具体实现**</ins>,涉及哪些组件之间进行交互,可以用1、2、3、...进行罗列。 > 如果是需求或者重构类的PR,需要<ins>**补充详细设计文档**</ins>(说明上下游组件关系、时序图、类图、DFX能力等内容)。 ## **3. 资料变更** > 请确认<ins>**是否涉及资料变更**</ins>。\ > 如涉及,需要在PR中体现,并简要说明修改内容。\ > 如不涉及,需填写“不涉及”。 ## **4. 接口变更** > 请确认<ins>**是否涉及跨代码仓或者客户面可见的接口变更**</ins>。\ > 如涉及,需详细说明接口以及对应的变更内容,同时需要在资料中体现。\ > 如不涉及,需填写“不涉及”。 ## **5. 测试结果** > 需体现<ins>**测试场景,测试方法以及测试结果**</ins>。\ > 测试用例设计时需考虑硬件、部署方式、功能、性能、精度、显存等维度。 ## **6. CheckList** > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] [ ] 代码注释完备 [ ] 正确记录维测日志 [ ] 是否有UT用例 [ ] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-PyMotor!218 | 2 个月前 | |
[feature] 支持 Prefill 跨机 Pipeline Parallel 拉起 Co-authored-by: Jechin<yuzechen1@huawei.com> # message auto-generated for no-merge-commit merge: !653 merge feature/prefill-cross-node-pp into master [feature] 支持 Prefill 跨机 Pipeline Parallel 拉起 Created-by: Jechin Commit-by: Jechin Merged-by: towncharlie Description: ## **1. 合入背景** Fixes [#389](https://gitcode.com/Ascend/MindIE-Motor/issues/389) Prefill 跨机 Pipeline Parallel(如 TP=16、PP=2、nnodes=2)场景下,控制面仍按“单机并行积”计算 local_world_size(pcp×tp×pp),导致本机设备数校验失败、Endpoint 为空;同时 master_addr=placeholder / 静态 node_rank 会盖住运行时注入,分布式初始化无法连通。Assembler 在无 Endpoint 时还会误报 start 成功。本 PR 补齐跨机 PP 与跨机 PCP 共用的 nnodes 路径,并让 Deployer 从 vLLM 脚本正确生成 PP/nnodes 配置;并行度读取统一为 CLI 整数优先、缺省回退 kv_connector_extra_config(含 pp_size)。 ## **2. 修改内容** 1. **NodeManager 配置**(motor/config/node_manager.py) - 跨机时按 (pcp×tp×pp)//nnodes 折算本机 local_world_size(覆盖 PP/PCP) - pcp×pp 不能被 nnodes 整除时直接报错,避免错误拓扑静默通过 2. **EngineServer VLLMConfig**(motor/engine_server/core/vllm/vllm_config.py) - 跨机场景强制覆盖 master_addr / node_rank / headless,不再被 placeholder 挡住 - Mooncake kv extra 合并并行度时保留用户字段(如 pp_layer_partition) 3. **Controller InstanceAssembler**(motor/controller/core/instance_assembler.py) - 所有 NodeManager 均无 Endpoint 时,_send_start_command 返回失败并打 ERROR,禁止假成功 4. **Deployer 转换**(examples/deployer/config_tool/vllm_to_motor.py) - 保留并正确写出 pipeline_parallel_size,按 tp×pp 推导 Pod / nnodes - 跨机时写入 nnodes / master-port;不写 master-addr / node-rank(运行时注入) - **dp/tp/pp 统一读取优先级**:命令行给了正整数用 CLI,否则回退 kv_connector_extra_config 的 dp_size / tp_size / pp_size(kv 中的 size 在写出前剥离) - 去除硬件侧强制 remap tp/dp;infer_*_motor_deploy_config 回传 nnodes,与跨机 engine 注入共用一次 _infer_pod_layout - 抽取 hybrid 默认 deploy / 权重挂载路径 / preset+cards 等重复逻辑,降低漂移风险 5. **UT** - 覆盖 PP 折算、不可整除、placeholder 覆盖、kv 字段保留、空 Endpoint start 失败 - Deployer:CLI>kv、仅 kv 回退(含 pp_size)、跨机 nnodes/master-port、跳过脚本透传多机键等 **进程视图** mermaid flowchart LR subgraph deploy [Deploy] script["vLLM serve 脚本\nCLI 与 kv extra"] conv["vllm_to_motor\nCLI大于kv"] uc["user_config\nPP nnodes master-port"] end subgraph control [Control Plane] nm0["NodeManager node_rank=0"] nm1["NodeManager node_rank=1"] asm["InstanceAssembler"] end subgraph engine [Engine] es0["EngineServer PP stage0"] es1["EngineServer PP stage1 headless"] end script --> conv --> uc uc --> nm0 uc --> nm1 nm0 -->|"Register local_world_size"| asm nm1 -->|"Register local_world_size"| asm asm -->|"StartCmd master_dp_ip/node_rank"| nm0 asm -->|"StartCmd"| nm1 nm0 --> es0 nm1 --> es1 es0 <-->|"master-port rendezvous"| es1 ## **3. 资料变更** 不涉及仓库内用户文档更新(Deployer README / 跨机说明未改)。 ## **4. 接口变更** 涉及配置约定(客户面可见): - Prefill 跨机 PP 需配置 pipeline_parallel_size、nnodes、master-port;**不要**配置 master-addr / node-rank - Deployer 从 vLLM 脚本转换时会自动生成上述项;pipeline_parallel_size 不再被强制改写为 1 - Deployer 并行度语义:--data/tensor/pipeline-parallel-size 正整数优先于 kv extra 的 dp_size/tp_size/pp_size;二者皆无时 dp/tp 走手动占位提示,pp 缺省为 1 - 无新增/变更 HTTP API ## **5. 测试结果** (自行补充) ## **6. CheckList** [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!653 | 1 天前 | |
[fix] 修复Coordinator测试用例在不同python版本现象不同的bug。【部分python版本会出现失败】 Co-authored-by: 吕有辉<lvyouhui@huawei.com> # message auto-generated for no-merge-commit merge: !116 merge master into master [fix] 修复Coordinator测试用例在不同python版本现象不同的bug。【部分python版本会出现失败】 Created-by: codeDogPro Commit-by: 吕有辉 Merged-by: towncharlie Description: ## **1. 合入背景** https://gitcode.com/Ascend/MindIE-PyMotor/issues/82 ## **2. 修改内容** 解决 from __future__ import annotations叠加不同pydantic版本引入的Request和'Request'解析逻辑差异的问题。 ## **3. 资料变更** 不涉及 ## **4. 接口变更** 不涉及 ## **5. 测试结果** 验证ok ## **6. CheckList** > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-PyMotor!116 | 3 个月前 | |
[test] ut耗时与warning告警优化 Co-authored-by: Jechin<yuzechen1@huawei.com> # message auto-generated for no-merge-commit merge: !269 merge test/ut-speedup-and-warnings-report into master [test] ut耗时与warning告警优化 Created-by: Jechin Commit-by: Jechin Merged-by: towncharlie Description: ## **1. 合入背景** > 请描述为什么要做这个PR内的改动。\ > 如涉及,请关联前序PR或同特性/需求下的其他PR。\ > 如果是修复之前PR引入的问题,请关联引入问题的PR。\ > 请通过#ISSUE ID关联issue。\ > 注意: Fixes #ISSUE ID会自动关闭issue,如问题部分解决请不要使用Fixes,可以用Fix part of #ISSUE ID替代. Fixes [#171](https://gitcode.com/Ascend/MindIE-PyMotor/issues/171) ## **2. 修改内容** > 请<ins>**描述修改内容的具体实现**</ins>,涉及哪些组件之间进行交互,可以用1、2、3、...进行罗列。 > 如果是需求或者重构类的PR,需要<ins>**补充详细设计文档**</ins>(说明上下游组件关系、时序图、类图、DFX能力等内容)。 | 文件 | 改动性质 | |------|----------| | pytest.ini | 移除第三方 warning 过滤 | | tests/run_tests.sh | warning 不再导致失败 | | tests/coordinator/router/test_router_cdp_separation.py | CDP 重试加速 | | tests/engine_server/core/test_sim_inference.py | health_check 加速 | | tests/coordinator/test_http_server.py | 限流 mock + pylint/ruff 修复 | > 全量并行 UT 耗时从约 31s 降至约 5s(优化前后对比验证过)。 ## **3. 资料变更** > 请确认<ins>**是否涉及资料变更**</ins>。\ > 如涉及,需要在PR中体现,并简要说明修改内容。\ > 如不涉及,需填写“不涉及”。 不涉及 ## **4. 接口变更** > 请确认<ins>**是否涉及跨代码仓或者客户面可见的接口变更**</ins>。\ > 如涉及,需详细说明接口以及对应的变更内容,同时需要在资料中体现。\ > 如不涉及,需填写“不涉及”。 不涉及 ## **5. 测试结果** > 需体现<ins>**测试场景,测试方法以及测试结果**</ins>。\ > 测试用例设计时需考虑硬件、部署方式、功能、性能、精度、显存等维度。 已测试 ## **6. CheckList** > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-PyMotor!269 | 1 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 9 天前 | ||
| 1 个月前 | ||
| 1 天前 | ||
| 1 天前 | ||
| 9 天前 | ||
| 1 天前 | ||
| 7 小时前 | ||
| 2 个月前 | ||
| 1 天前 | ||
| 3 个月前 | ||
| 1 个月前 |