# PrecisionComparer **Repository Path**: zangqx/precision-comparer ## Basic Information - **Project Name**: PrecisionComparer - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-18 - **Last Updated**: 2026-04-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 模型精度对比工具 (PrecisionComparer) 自动对比baseline和test模型训练的精度(loss和grad norm),并在发现差异时,根据日志和msprobe信息分析引入精度不一致的api或算子, 并给出调用的代码位置。打印确认代码的输入输出,比较两个模型的打印日志;如果不是第一个引起精度问题的代码位置,则根据msporbe的调用栈,获取所有的调用函数,在函数的起始位置加打印定位引起精度问题的函数。 ## 功能特点 * 支持本地执行和SSH远程执行两种模式 * 启动baseline和test模型训练 * 训练完成后提取训练日志和msprobe数据,对比精度指标 * 对比日志loss和grad_norm定位引起精度不一致的api或算子,并给出代码位置 * 自动调用DeepSeek分析代码输入输出参数,智能注入调试打印信息 * 如果无法根据训练日志和msprobe数据分析引起精度的代码位置,则自动添加调试打印信息定位差异 ## 安装依赖 ```bash cd PrecisionComparer pip install -r requirements.txt ``` ## 配置 编辑 `config.json` 配置文件: ```json { "baseline": { "mode": "local", "log_path": "/path/to/baseline/logs", "code_path": "/path/to/baseline/code", "run_script": "bash /path/to/baseline/run_train.sh", "ssh": { "host": "10.170.27.151", "username": "root", "port": 22, "password": "your_password" } }, "test": { "mode": "local", "log_path": "/path/to/test/logs", "code_path": "/path/to/test/code", "run_script": "bash /path/to/test/run_train.sh", "ssh": { "host": "10.170.27.151", "username": "root", "port": 22, "password": "your_password" } }, "msprobe": { "baseline_data_dir": "/path/to/baseline/msprobe_data", "test_data_dir": "/path/to/test/msprobe_data", "parse_code_dir": "/PanGu/", "compare_output_dir": "/path/to/baseline_vs_test/result_of_operator_operation_diff" }, "debug": { "max_iterations": 10, "tolerance": 0.001, "log_keywords": ["mtp head 0 lm loss", "grad norm"], "trace_threshold": 0.001 } } ``` ### 配置说明 | 字段 | 说明 | |------|------| | `mode` | 执行模式:`local`(本地执行)或 `remote`(SSH远程执行) | | `log_path` | 训练日志文件路径 | | `code_path` | 代码目录路径 | | `run_script` | 启动训练的脚本命令 | | `ssh` | SSH配置(仅remote模式需要) | ## msprobe 数据说明 ### 文件目录结构 ``` ├── rank0 # rank id │   ├── construct.json # 忽略此文件 │   ├── dump.json # 算子的输入输出tensor信息:数据类型、 shape、最大值、最小值、均值、md5值 │   └── stack.json # 算子或者接口名对应的代码调用栈 ├── rank1 │   ├── construct.json │   ├── dump.json │   └── stack.json ├── rank2 │   ├── construct.json │   ├── dump.json │   └── stack.json ... ``` ### msprobe compare命令 ```bash export PYTHONPATH=/disk2/z30015122/mstt-master/debug/accuracy_tools/:$PYTHONPATH msprobe compare -tp {test_data_dir} -gp {baseline_data_dir} -o {compare_output_dir} ``` - baseline_data_dir: 是baseline模型mspore数据存放的目录,路径从config中读取 - test_data_dir: 是test模型mspore数据存放的目录,路径从config中读取 - compare_output_dir: msprobe compare工具对比结果存放目录,路径从config中读取 ### msprobe compare 对比结果表格说明 - 表格的每一行是一个算子的输入或输出tensor值的对比数据 - 列'NPU Name'和'Bench Name'是tensor名称 - 列'Max diff'是最大值差值 - 列'Min diff'是最小值差值 - 列'Mean diff'是均值插值 - 列'NPU_Stack_Info'是该算子的代码调用栈,调用栈格式如下: ``` ['File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/mstt-master/debug/accuracy_tools/msprobe/core/data_dump/api_registry.py, line 96, in api_function, \n return api_instance(*args, **kwargs)', "File /home/ma-user/anaconda3/envs/PyTorch-2.6.0/lib/python3.11/site-packages/torch/utils/backend_registration.py, line 148, in wrap_tensor_to, \n return self.to(device=torch.device(f'{custom_backend_name}:{device_idx}'), non_blocking=non_blocking, **kwargs)", "File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pangu/training/utils.py, line 742, in get_batch_on_this_tp_rank, \n 'tokens': data[tokens_key].cuda(non_blocking=True),", 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pretrain_gpt.py, line 199, in get_batch, \n batch, actual_seq_len, mome_mask = get_batch_on_this_tp_rank(data_iterator)', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pretrain_gpt.py, line 599, in forward_step, \n dict_values, actual_seq_len, mome_mask = get_batch(data_iterator)', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/pangu_sophon_hsdp/third_party/MindSpeed/mindspeed/core/pipeline_parallel/schedules.py, line 91, in forward_step, \n output_tensor, loss_func = forward_step_func(data_iterator, model)', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/pangu_sophon_hsdp/third_party/MindSpeed/mindspeed/core/performance/auto_pipeline_perf/schedules.py, line 55, in wrapper, \n output_tensor = fn(*args, **kwargs)', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pangu/core/pipeline_parallel/schedules.py, line 354, in forward_backward_no_pipelining, \n output_tensor = forward_step(', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pangu/training/training.py, line 1135, in train_step, \n losses_reduced = forward_backward_func(', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pangu/training/training.py, line 1472, in train, \n train_step(forward_step_func,', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pangu/utils.py, line 599, in wrapper, \n return func(*args, **kwargs)', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pangu/training/training.py, line 695, in pretrain, \n iteration, num_floating_point_operations_so_far = train(', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pretrain_gpt.py, line 771, in main, \n pretrain(train_valid_test_datasets_provider,', 'File /home/ma-user/work/bucket-pangu-green-guiyang/z30015122/02_HyperParallel/openPangu2-34B-fsdp/PanGu/pretrain_gpt.py, line 789, in , \n main()'] ``` ## 使用方法 ### 直接运行 ```bash cd PrecisionComparer python precision_comparer.py ``` ### 命令行参数 ```bash python precision_comparer.py --config custom_config.json --max-iterations 20 --tolerance 0.0005 ``` * `--config`: 指定配置文件路径 * `--max-iterations`: 自行添加打印信息并执行训练,对比打印结果的最大执行次数 * `--tolerance`: 设置容忍误差范围 ### 作为Skill使用 ```bash /precision-comparer ``` 或指定参数: ```bash /precision-comparer max_iterations=20 tolerance=0.0005 ``` ## 工作流程 1. 读取配置文件中的baseline和test信息 2. 根据mode配置初始化执行器(本地或SSH远程) 3. 启动baseline和test训练 4. 等待训练完成,如果训练日志中包含"training success",则表示训练结束 5. 提取日志中的"mtp head 0 lm loss"和"grad norm" 6. 对比两个配置的精度指标 7. **工作流程分支**: - **如果精度一致**: 任务完成 - **如果精度不一致**: - 使用msprobe compare工具对比msprobe数据,对比工具使用方式参考msprobe compare命令章节 - 从对比excel中找到第一个不一致的tensor,从NPU_Stack_Info列获取该算子的调用栈,当前只对比"_rank0_"的数据。 - 解析调用栈获取代码位置,读取该行代码 - 调用DeepSeek分析代码的输入输出参数 - 在代码行前注入输入参数打印,在代码行后, 注入输出参数打印 - 再重新拉起训练,训练结束后再对比添加的打印日志 - 如果输入的打印日志一致,输出不一致,说明此算子可能存在精度问题,任务结束 - 如果输入的打印不一致,从NPU_Stack_Info列获取所有的tensor调用栈,解析出模型代码调用列表call_func_infos=[file_path: [{func_name,line_num}]],file_path代码文件路径,func_name为函数名称,line_num为调用的代码位置,重复的file_path只解析一次。 - 根据所有的call_func_infos.file_path的路径,读取每一个文件内容,调用parse_func_for_code函数返回all_func_infos - 根据call_func_infos的file_path和line_num在all_func_infos提供的函数信息找到对应的函数位置,在函数输入输出位置添加打印输入输出参数 - 然后再重启训练。 - 训练结束后,读取日志比较打印的日志,找到第一个打印不一致的地方,告知用户。 - **只定位精度不一致的代码位置,不进一步修复代码** ## 精度对比标准 * 对比指标:loss 和 grad norm * 容忍误差:默认 0.001(可在配置中修改) * 一致判断:所有步骤的loss和grad norm差异都在容忍范围内 ## 输出示例 ``` ============================================================ 开始第 1 次对比 ============================================================ [1/6] 连接到baseline服务器... 正在连接到 root@10.170.27.151:22 成功连接到 10.170.27.151 [2/6] 连接到test服务器... 正在连接到 root@10.170.27.151:22 成功连接到 10.170.27.151 ... ================================================== 精度对比结果: ================================================== Loss - 平均差异: 0.000123, 最大差异: 0.000456 Grad Norm - 平均差异: 0.000234, 最大差异: 0.000567 精度一致性: ✓ 一致 ================================================== ``` ## 注意事项 1. 本地模式下确保训练脚本可以直接执行 2. 远程模式下确保配置文件中的SSH密码正确 3. 确保日志路径存在且有权限访问 4. 建议在运行前手动测试一次训练脚本,确保配置正确 5. 代码修改功能仅用于定位差异,实际修改需要手动确认 6. DeepSeek API密钥需要设置环境变量 `DEEPSEEK_API_KEY` 或在tools.py中配置 ## 故障排除 **本地执行失败** * 检查训练脚本路径是否正确 * 检查脚本是否有执行权限 * 检查工作目录是否存在 **SSH连接失败** * 检查主机、端口、用户名、密码是否正确 * 检查网络连接和防火墙设置 **找不到日志文件** * 检查日志路径配置是否正确 * 确认训练脚本是否正常启动 * 检查日志文件格式和命名规则 **精度指标提取失败** * 检查日志中是否包含"loss"和"grad norm"关键词 * 可以根据实际情况修改 `log_parser.py`中的正则表达式 **DeepSeek API调用失败** * 检查API密钥是否正确 * 检查网络连接是否正常