| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
[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 | 2 天前 | |
[refractor] Controller代码微重构,提升代码可维护性 Co-authored-by: 吕有辉<lvyouhui@huawei.com> # message auto-generated for no-merge-commit merge: !623 merge refractor/controller into master [refractor] Controller代码微重构,提升代码可维护性 Created-by: codeDogPro Commit-by: 吕有辉 Merged-by: tobking Description: # Controller 重构 PR 说明 ISSUE:https://gitcode.com/Ascend/MindIE-Motor/issues/368 关联 PR:[NodeManager 重构](https://gitcode.com/Ascend/MindIE-Motor/pull/620) ## 1. 合入背景 Controller 的 main.py 将模块管理、配置更新传播、daemon loop、信号处理等逻辑全部写在模块级全局变量和函数中,与 NodeManager 的 main.py 存在大量重复代码。此前 NodeManager 已完成重构(提取 Application 基类和 NodeManager 类),本次将相同模式应用到 Controller,并同步 daemon_loop_interval 热更新能力。 ## 2. 修改内容 ### 2.1 ControllerConfig 新增 daemon_loop_interval 配置 **文件**: motor/config/controller.py 新增 ControllerConfig.daemon_loop_interval: float = 5.0,支持在 user_config.json 中配置 daemon loop 检查间隔,默认 5 秒。 ### 2.2 Controller 类同步 check_interval 能力 **文件**: motor/controller/controller.py 1. Controller.__init__ 传入 check_interval=config.daemon_loop_interval 到 Application 基类。 2. 重写 _refresh_check_interval(),配置热更新时自动同步间隔。 ### 2.3 改动文件清单 | 文件 | 改动类型 | |------|----------| | motor/config/controller.py | 新增 daemon_loop_interval 字段 | | motor/controller/controller.py | 传入 check_interval + 重写 _refresh_check_interval | ## 3. 资料变更 不涉及。 ## 4. 接口变更 不涉及。 ## 5. 测试结果  python -m pytest tests/controller/ -q 544 passed in 12.37s ## 6. CheckList - [x] 代码注释完备 - [x] 正确记录维测日志 - [x] 是否有UT用例(全量 544 passed) - [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!623 | 1 天前 | |
[refractor] Controller代码微重构,提升代码可维护性 Co-authored-by: 吕有辉<lvyouhui@huawei.com> # message auto-generated for no-merge-commit merge: !623 merge refractor/controller into master [refractor] Controller代码微重构,提升代码可维护性 Created-by: codeDogPro Commit-by: 吕有辉 Merged-by: tobking Description: # Controller 重构 PR 说明 ISSUE:https://gitcode.com/Ascend/MindIE-Motor/issues/368 关联 PR:[NodeManager 重构](https://gitcode.com/Ascend/MindIE-Motor/pull/620) ## 1. 合入背景 Controller 的 main.py 将模块管理、配置更新传播、daemon loop、信号处理等逻辑全部写在模块级全局变量和函数中,与 NodeManager 的 main.py 存在大量重复代码。此前 NodeManager 已完成重构(提取 Application 基类和 NodeManager 类),本次将相同模式应用到 Controller,并同步 daemon_loop_interval 热更新能力。 ## 2. 修改内容 ### 2.1 ControllerConfig 新增 daemon_loop_interval 配置 **文件**: motor/config/controller.py 新增 ControllerConfig.daemon_loop_interval: float = 5.0,支持在 user_config.json 中配置 daemon loop 检查间隔,默认 5 秒。 ### 2.2 Controller 类同步 check_interval 能力 **文件**: motor/controller/controller.py 1. Controller.__init__ 传入 check_interval=config.daemon_loop_interval 到 Application 基类。 2. 重写 _refresh_check_interval(),配置热更新时自动同步间隔。 ### 2.3 改动文件清单 | 文件 | 改动类型 | |------|----------| | motor/config/controller.py | 新增 daemon_loop_interval 字段 | | motor/controller/controller.py | 传入 check_interval + 重写 _refresh_check_interval | ## 3. 资料变更 不涉及。 ## 4. 接口变更 不涉及。 ## 5. 测试结果  python -m pytest tests/controller/ -q 544 passed in 12.37s ## 6. CheckList - [x] 代码注释完备 - [x] 正确记录维测日志 - [x] 是否有UT用例(全量 544 passed) - [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!623 | 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 | 2 天前 | |
add storage feature Co-authored-by: supermario_leo<leo.stack@outlook.com> # message auto-generated for no-merge-commit merge: !440 merge feature_add_ucm into master add storage feature Created-by: leo6393 Commit-by: supermario_leo Merged-by: towncharlie Description: ## **1. 合入背景** 在分布式 PD 架构上接入 **UCMConnector** 作为 KV 存储层,为 Prefill 节点提供前缀缓存(prefix cache)复用能力,降低重复前缀的 TTFT、提升整体吞吐。 由于 UCM 的 storage_backends 需要一块 **P/D 跨节点共享**的持久化存储,本分支同时补齐了通用的**引擎 Pod 存储能力**(不绑定 UCM),作为 UCM 前缀缓存池的落盘载体。 - 关联特性:UCM 前缀缓存接入(分布式 PD) - 不涉及对既有 PR 问题的修复 ## **2. 修改内容** 1. **UCM Connector 接入(motor/engine_server/core/vllm/vllm_config.py)** - MultiConnector 场景下识别 connectors[1] = UCMConnector:提前处理并强制 kv_role = kv_both(UCM 在 P/D 两端均双向 store),**不注入任何 rpc port**,避免污染 UCM 的内联 kv_connector_extra_config,处理后 return early。 - 独立 UCMConnector 在 prefill/decode 角色下 **fail loud**(该拓扑需额外 dispatch/profile 工作,当前不支持);union 角色原样透传。 - AscendStoreConnector / MooncakeStore 分支行为保持不变,报错信息修正为打印实际 connector 名。 2. **端口注入适配(motor/config/endpoint.py、motor/config/node_manager.py)** - MultiConnector 组装时,UCM store 无 lookup_rpc_port。改用 .get() 判断 connector 类型,**仅跳过 UCM**;其余 store(如 AscendStore)保持直接索引 —— 真正缺失端口时仍按原逻辑 fail fast,不被静默跳过。 3. **常量新增(motor/engine_server/constants/constants.py、motor/config/node_manager.py)** - UCM_CONNECTOR = "UCMConnector"、KV_BOTH = "kv_both"、KV_CONNECTOR_MODULE_PATH。 4. **通用引擎 Pod 存储能力(新增 examples/deployer/lib/generator/storage.py)** - motor_deploy_config.storage 为**列表**,每条目必须声明 type: - pvc —— 两种互斥模式:storage_class_name 动态创建 PVC / claim_name **挂载已有 PVC**(不生成 PVC 对象,且与 size/access_mode/storage_class_name 互斥,混填/漏填均 fail loud;claim_name 用于非 pvc 类型也会被拒绝)。 - nfs —— k8s 原生 NFS 卷直挂(server+path),无需 CSI/供给器。 - hostpath —— 节点本地目录直挂。 - dshm_size —— 独立抬高 /dev/shm emptyDir sizeLimit(容纳 UCM CacheStore),带无单位值校验。 - 挂载逻辑幂等,复用到 engine.py / infer_service.py / single_container.py 三条部署路径;卷名/动态 PVC 名按序号自动生成(mindie-motor-store-<i>)。 5. **示例与镜像** - examples/infer_engines/vllm/ucm_pd/(README + user_config.json):分布式 PD + UCM 内联配置示例。 - docker/mindie-motor-vllm-ucm/(Dockerfile + README):UCM 叠加镜像。 ## **3. 资料变更** **涉及。** - 新增 examples/infer_engines/vllm/ucm_pd/README.md:UCM 前缀缓存拓扑、存储三种类型(pvc/nfs/hostpath)字段表、动态创建 / 挂已有 PVC(claim_name)两种写法示例、dshm_size 说明及硬约束(storage_backends == mount_path)。 - 新增 docker/mindie-motor-vllm-ucm/README.md:UCM 叠加镜像构建说明。 ## **4. 接口变更** **涉及客户面可见的配置项变更(user_config.json),不涉及跨代码仓 API 变更。** - kv_connector 支持 UCMConnector,及 MultiConnector 中内嵌 UCM 作为 connectors[1];需配套 kv_connector_module_path。 - motor_deploy_config 新增 storage 列表(type: pvc/nfs/hostpath,pvc 支持 claim_name 挂已有卷)与 dshm_size。 - 均为新增可选项,对存量配置向后兼容。 ## **5. 测试结果** 新增 / 覆盖 UT: | 用例文件 | 用例数 | 覆盖场景 | |---|---|---| | tests/examples/deployer/test_storage.py | 22 | pvc/nfs/hostpath 三类挂载;pvc 动态创建 vs claim_name 挂已有;参数互斥与缺失校验;非 pvc 类型拒绝 claim_name;多条目/同 claim 多挂载点;挂载幂等;dshm_size 设置与无单位校验 | | tests/engine_server/core/test_vllm_config.py | 13 | UCM kv_role=kv_both、不注入端口;独立 UCM 在 P/D 角色 fail loud;MultiConnector 内嵌 UCM;既有 mooncake/ascend 分支回归 | | tests/node_manager/test_config.py | 33 | MultiConnector 组装跳过 UCM 端口注入;非 UCM store 缺端口仍 fail fast | - 部署方式维度:覆盖 Deployment(engine)、InferServiceSet、single-container 三条路径的存储挂载。 - 本地已执行 deployer UT 套件:54 passed;test_vllm_config.py / test_config.py 依赖运行时环境,请在集成环境执行确认。 - 建议补充:UCM 叠加镜像 + 实机分布式 PD 端到端前缀缓存命中 / TTFT 验证。 ## **6. CheckList** - [x] 代码注释完备 - [x] 正确记录维测日志 - [x] 是否有UT用例 - [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题(本次改动为配置解析 / YAML 生成,无新增多线程逻辑) See merge request: Ascend/MindIE-PyMotor!440 | 12 天前 | |
【feature】kv-conductor Co-authored-by: 吕有辉<lvyouhui@huawei.com> # message auto-generated for no-merge-commit merge: !568 merge feat/kv-conductor into master 【feature】kv-conductor Created-by: codeDogPro Commit-by: 吕有辉 Merged-by: towncharlie Description: ## **1. 合入背景** https://gitcode.com/Ascend/MindIE-PyMotor/issues/338 内部subCMC已经评审,该大PR同意合入 ## **2. 修改内容** 1、引入kv-conductor【rust源代码,测试代码,设计文档】 2、Coordinator conductor client适配kv-conductor 3、新增kv-conductor config 4、kvcache_affine.md重写,以kv-conductor为准 5、build.sh集成kv-conductor二进制打包进whl的能力,支持跳过kv-conductor打包,便于在无rust编译环境上构建基础组件 ## **3. 资料变更** 涉及 ## **4. 接口变更** 涉及 ## **5. 测试结果** whl包版kv-conductor拉起成功,请求命中匹配成功 Looking in indexes: https://repo.huaweicloud.com/repository/pypi/simple, https://mirrors.huaweicloud.com/ascend/repos/pypi Processing ./dist/motor-0.1.0-py3-none-any.whl Installing collected packages: motor Attempting uninstall: motor Found existing installation: motor 0.1.0 Uninstalling motor-0.1.0: Successfully uninstalled motor-0.1.0 Successfully installed motor-0.1.0 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv [notice] A new release of pip is available: 24.0 -> 26.1.2 [notice] To update, run: pip install --upgrade pip Current node role: ROLE=kv_conductor Starting KV Conductor on 0.0.0.0:13333 2026-07-21T17:12:09.17062356+08:00 INFO scoring config hbm_weight=3 cpu_weight=2 disk_weight=1 2026-07-21T17:12:09.17093877+08:00 INFO KV conductor starting on 0.0.0.0:13333 2026-07-21T17:12:10.44555639+08:00 TRACE connection 192.168.196.1:50480 accepted 2026-07-21T17:12:10.44581192+08:00 TRACE connection 192.168.196.1:50480 closed 2026-07-21T18:18:48.26729199+08:00 DEBUG request{method=POST uri=/query version=HTTP/1.1}: started processing request 2026-07-21T18:18:48.26737949+08:00 DEBUG request{method=POST uri=/query version=HTTP/1.1}: query request model=Qwen3-30B-A3B-W8A8 tenant=default num_tokens=1503 2026-07-21T18:18:48.26740762+08:00 DEBUG request{method=POST uri=/query version=HTTP/1.1}: find_matches seq_len=12 depth=11 active_workers=2 elapsed_us=13 2026-07-21T18:18:48.26741747+08:00 DEBUG request{method=POST uri=/query version=HTTP/1.1}: hash_computed num_tokens=1503 block_size=128 num_hashes=12 hash_us=2 scores=2 2026-07-21T18:18:48.26743069+08:00 DEBUG request{method=POST uri=/query version=HTTP/1.1}: query profile num_tokens=1503 block_size=128 hash_us=37 total_us=43 2026-07-21T18:18:48.26745731+08:00 DEBUG request{method=POST uri=/query version=HTTP/1.1}: finished processing request latency=0 ms status=200 Qwen3-30B-A3B,Prefill DP2,Decode DP2测试如下: 发送8个请求,gsm8 未开启亲和性调度: ╒══════════════════════════╤═════════╤═════════════════╤════════════════╤═════════════════╤═════════════════╤═════════════════╤═════════════════╤═════════════════╤═════╕ │ Performance Parameters │ Stage │ Average │ Min │ Max │ Median │ P75 │ P90 │ P99 │ N │ ╞══════════════════════════╪═════════╪═════════════════╪════════════════╪═════════════════╪═════════════════╪═════════════════╪═════════════════╪═════════════════╪═════╡ │ E2EL │ total │ 7389.6 ms │ 4197.7 ms │ 8487.4 ms │ 8063.4 ms │ 8298.8 ms │ 8377.5 ms │ 8476.4 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ TTFT │ total │ 311.4 ms │ 226.1 ms │ 484.5 ms │ 284.1 ms │ 373.7 ms │ 409.9 ms │ 477.0 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ TPOT │ total │ 15.7 ms │ 15.3 ms │ 15.9 ms │ 15.8 ms │ 15.9 ms │ 15.9 ms │ 15.9 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ ITL │ total │ 15.6 ms │ 0.0 ms │ 48.4 ms │ 15.6 ms │ 15.8 ms │ 16.0 ms │ 20.1 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ InputTokens │ total │ 1491.5 │ 1460.0 │ 1545.0 │ 1490.5 │ 1499.25 │ 1515.6 │ 1542.06 │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ OutputTokens │ total │ 452.125 │ 242.0 │ 512.0 │ 509.0 │ 512.0 │ 512.0 │ 512.0 │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ OutputTokenThroughput │ total │ 60.9652 token/s │ 57.651 token/s │ 63.2079 token/s │ 61.2631 token/s │ 62.0915 token/s │ 63.0926 token/s │ 63.1963 token/s │ 8 │ ╘══════════════════════════╧═════════╧═════════════════╧════════════════╧═════════════════╧═════════════════╧═════════════════╧═════════════════╧═════════════════╧═════╛ 开启亲和性: ╒══════════════════════════╤═════════╤═════════════════╤═════════════════╤═════════════════╤═════════════════╤═════════════════╤═════════════════╤═════════════════╤═════╕ │ Performance Parameters │ Stage │ Average │ Min │ Max │ Median │ P75 │ P90 │ P99 │ N │ ╞══════════════════════════╪═════════╪═════════════════╪═════════════════╪═════════════════╪═════════════════╪═════════════════╪═════════════════╪═════════════════╪═════╡ │ E2EL │ total │ 7240.3 ms │ 4261.9 ms │ 8632.0 ms │ 7745.1 ms │ 8326.5 ms │ 8438.4 ms │ 8612.6 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ TTFT │ total │ 320.5 ms │ 241.6 ms │ 519.1 ms │ 260.4 ms │ 393.4 ms │ 432.8 ms │ 510.5 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ TPOT │ total │ 15.8 ms │ 15.4 ms │ 15.9 ms │ 15.9 ms │ 15.9 ms │ 15.9 ms │ 15.9 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ ITL │ total │ 15.7 ms │ 0.0 ms │ 45.1 ms │ 15.6 ms │ 15.9 ms │ 16.1 ms │ 23.1 ms │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ InputTokens │ total │ 1491.5 │ 1460.0 │ 1545.0 │ 1490.5 │ 1499.25 │ 1515.6 │ 1542.06 │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ OutputTokens │ total │ 439.125 │ 254.0 │ 512.0 │ 481.5 │ 512.0 │ 512.0 │ 512.0 │ 8 │ ├──────────────────────────┼─────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────┤ │ OutputTokenThroughput │ total │ 60.5041 token/s │ 58.5203 token/s │ 62.9559 token/s │ 60.4373 token/s │ 61.3642 token/s │ 61.9798 token/s │ 62.8583 token/s │ 8 │ ╘══════════════════════════╧═════════╧═════════════════╧═════════════════╧═════════════════╧═════════════════╧═════════════════╧═════════════════╧═════════════════╧═════╛ ## **6. CheckList** > PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x] [ ] 代码注释完备 [ ] 正确记录维测日志 [ ] 是否有UT用例 [ ] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-Motor!568 | 9 天前 | |
[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 | 2 天前 | |
[feature] Print MindIE-Motor ASCII logo on component startup Co-authored-by: Jechin<yuzechen1@huawei.com> # message auto-generated for no-merge-commit merge: !588 merge feat/startup-logo into master [feature] Print MindIE-Motor ASCII logo on component startup Created-by: Jechin Commit-by: Jechin Merged-by: towncharlie Description: ## **1. 合入背景** 组件启动缺少统一品牌识别,且 setup.py / motor.__version__ / version.info 三处版本硬编码不一致。 Fixes #347 双合 PR:[#589](https://gitcode.com/Ascend/MindIE-PyMotor/merge_requests/589)(合入 v3.1.0)。 ## **2. 修改内容** 1. 新增 motor/common/utils/startup_banner.py,以 Unicode Block MOTOR 字样打印启动 Banner;副标题为 MindIE-Motor · v{version} · {role},与字画左对齐,上方留空行。 2. 在 coordinator / controller / node_manager 的 main 入口调用 log_startup_banner(不接入 EngineServer)。 3. 支持环境变量 MOTOR_DISABLE_LOG_LOGO(与 vLLM 对齐):置 1 时不打印 ASCII 字画,改为单行 MindIE-Motor version …, role …;单容器启动脚本 all_combine_in_single_container.sh 中默认开启,避免多进程刷屏。 4. 以 motor/__init__.py 的 __version__(现为 3.1.0)为唯一版本源;setup.py 解析该字段作为 wheel 版本;build.sh 读取后写入 version.info 的 motor_version(兼容单/双引号),并删除未使用的 vllm_version / vllm_ascend_version 字段。 5. 安装文档/脚本中的 wheel 路径改为 motor-*.whl 通配,避免写死版本号。 6. 补充 tests/common/utils/test_startup_banner.py 单测(含 disable 环境变量路径)。 ## **3. 资料变更** 涉及:构建/部署文档与 ModelArts 安装示例中的 wheel 安装路径改为通配(motor-*.whl)。 ## **4. 接口变更** 不涉及跨仓或客户面接口变更。新增可选环境变量 MOTOR_DISABLE_LOG_LOGO(默认 0,关闭 logo 时设为 1)。 ## **5. 测试结果**   - 场景:本地渲染 Banner / UT;单容器脚本关闭 logo - 方法:pytest tests/common/utils/test_startup_banner.py;验证 setup.py/build.sh 读取版本与 __version__ 一致;MOTOR_DISABLE_LOG_LOGO=1 时输出单行文案 - 结果:单测通过;版本读取一致为 3.1.0 ## **6. CheckList** [x] 代码注释完备 [x] 正确记录维测日志 [x] 是否有UT用例 [x] 若涉及多线程场景,考虑了并发场景,不存在死锁问题 See merge request: Ascend/MindIE-PyMotor!588 | 9 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 2 天前 | ||
| 1 天前 | ||
| 1 天前 | ||
| 2 天前 | ||
| 12 天前 | ||
| 9 天前 | ||
| 2 天前 | ||
| 9 天前 |