diff --git a/profiler/msprof_analyze/README.md b/profiler/msprof_analyze/README.md index 6541310ee47c373b437fef7a89bc7728c1cd011a..96007c45dbb40f619fbe73f83061e2367b90c199 100644 --- a/profiler/msprof_analyze/README.md +++ b/profiler/msprof_analyze/README.md @@ -194,6 +194,12 @@ msprof-analyze -m [feature_option] -d [global_option] [analyze_ | slow_link | 集群慢链路异常分析 | - | | slow_rank_pp_stage | pp stage通信对比分析 | - | +#### 强化学习类特性 + +| 分析能力 | 介绍 | 介绍链接 | +|---------|----------------------------------------|-----| +| rl_analysis | 强化学习场景性能分析,提供多阶段mstx打点数据汇总、可视化timeline缩略图等能力。 | [link](./docs/features/rl_analysis.md) | + #### Host下发类特性 | 分析能力 | 介绍 | 介绍链接 | diff --git a/profiler/msprof_analyze/cluster_analyse/recipes/rl_analysis/rl_analysis.py b/profiler/msprof_analyze/cluster_analyse/recipes/rl_analysis/rl_analysis.py index a84609e27b7008fe3f2339396cb2f47552a7e500..1682168f1c03a049bcc6ece3fb368e5a361f816a 100644 --- a/profiler/msprof_analyze/cluster_analyse/recipes/rl_analysis/rl_analysis.py +++ b/profiler/msprof_analyze/cluster_analyse/recipes/rl_analysis/rl_analysis.py @@ -31,7 +31,9 @@ logger = get_logger() class RlAnalysis(BaseRecipeAnalysis): """Reinforcement Learning Profiling Data Analysis Recipe""" - + # RL Constant + ROLL = "roll" + # db table name TABLE_RL_EVENTS = "RlEvents" @@ -118,9 +120,11 @@ class RlAnalysis(BaseRecipeAnalysis): logger.warning("No valid data collected from any rank") return - self.events_summary = [] - for events in reduce_results: - self.events_summary.extend(events) + self.events_summary = [ + event + for events in reduce_results + for event in events + ] roll_rank_to_comm_groups = {} for event in self.events_summary: @@ -196,7 +200,7 @@ class RlAnalysis(BaseRecipeAnalysis): """Collect RL performance data from a single rank""" profiler_db_path = data_map.get(Constant.PROFILER_DB_PATH) rank_id = data_map.get(Constant.RANK_ID) - roll = data_map.get(Constant.ROLL) + roll = data_map.get(RlAnalysis.ROLL) if not profiler_db_path: logger.warning(f"Rank {rank_id}: profiler_db_path not found") @@ -207,12 +211,13 @@ class RlAnalysis(BaseRecipeAnalysis): def _get_rank_db_with_roll(self): """Get database path information for all ranks""" if self._rank_list != 'all': - logger.warning("RL analysis currently only supports processing all ranks") + logger.error("RL analysis currently only supports processing all ranks") + return [] rank_ids_with_roll = list(self._data_map.keys()) db_paths = [] for roll, rank_id in rank_ids_with_roll: rank_path = self._data_map[(roll, rank_id)] - db_path_dict = {Constant.RANK_ID: rank_id, Constant.ROLL: roll, Constant.PROFILER_DB_PATH: ""} + db_path_dict = {Constant.RANK_ID: rank_id, RlAnalysis.ROLL: roll, Constant.PROFILER_DB_PATH: ""} profiler_db_path = self._get_profiler_db_path(rank_id, rank_path) if os.path.exists(profiler_db_path): db_path_dict[Constant.PROFILER_DB_PATH] = profiler_db_path diff --git a/profiler/msprof_analyze/docs/features/rl_analysis.md b/profiler/msprof_analyze/docs/features/rl_analysis.md new file mode 100644 index 0000000000000000000000000000000000000000..9bbc4f56977ce86c118dfd66387dfa3bb01d4099 --- /dev/null +++ b/profiler/msprof_analyze/docs/features/rl_analysis.md @@ -0,0 +1,235 @@ +# RL Analysis 强化学习场景性能分析指导 + +## 概述 + +强化学习(Reinforcement Learning)后训练是当前AI训练的主流方式。VeRL、MindSpeed-RL、MindRLHF等框架支持多种强化学习算法,并均可在昇腾NPU设备上运行。 + +### 部署模式 + +强化学习训练支持两种部署模式: + +- **共卡部署**:每个节点运行一个进程,负责所有计算阶段(每个独立的计算阶段称为一个Roll),如下图左边所示 +- **分离部署**:节点分工协作,每个节点只负责特定步骤的计算,如下图右边所示 + +![reinforcement learning training](../source/img/reinforcement_learning_train.png) + +### 性能挑战与解决方案 + +强化学习场景各阶段可能存在资源利用不充分、负载不均等性能问题,对于全局的分析,端到端采集性能数据量过大,分析、定界问题效率较低 + + +为解决这些问题,MSTT提供了`rl_analysis`工具,具备以下核心能力: + +- **数据汇总**:提供标准化的强化学习各阶段mstx打点数据汇总能力,支持用户对mstx打点数据进行自定义操作 +- **可视化分析**:提供多种可视化功能,包括全局timeline缩略图、推理负载信息等 + +## 使用指南 + +### 第一步:性能数据采集 + +#### 支持的框架 + +各强化学习框架均支持通过YAML配置一键采集性能数据: + +| 框架名称 | 性能数据采集指导文档 | +|---------|-------------------| +| VeRL | [Ascend Profiling指导](https://github.com/volcengine/verl/blob/main/docs/ascend_tutorial/ascend_profiling.rst) | +| MindSpeed-RL | [Profiler功能说明](https://gitee.com/ascend/MindSpeed-RL/blob/master/docs/features/profiler.md) | +| MindRLHF | [Profiler功能说明](https://gitee.com/mindspore/mindrlhf/blob/master/docs/features/profiler.md) | + +#### 配置要求 + +采集性能数据时,请确保满足以下配置要求: + +1. **基础配置**: + - 设置`export_type=db` + - 开启`mstx`开关 + - 关闭`profiler_with_cpu`(不采集torch op数据,减少数据量) + - 设置`profile_level`为`Level_none`(不采集device算子执行数据,减少数据量) + - 在`torch_npu.profiler._ExperimentalConfig`中设置`mstx_domain_exclude`为`["communication"]`(不采集通讯内置打点,减少数据量) + +1. **计算阶段标识**: + 在分离部署场景,不同组device负责不同的计算任务,为了区分这些计算任务,以观察不同计算任务间是否存在空泡,可以通过`add_metadata`添加每份profiler数据的计算阶段标识: + + ```python + # 在强化学习框架profiler代码中,在profiler.start到profiler.stop之间添加roll标识 + # 以VeRL为例,在verl/utils/profiler/mstx_profile.py的NPUProfiler类的start函数中添加该计算阶段的标识: + def start(self, **kwargs): + ... + self.profiler_npu.start() + self.profiler_npu.add_metadata_json('roll', json.dumps("update")) # update标识profiler采集的是update阶段性能数据 + ``` + 共卡部署场景采集性能数据时,可以不进行标识。 + +2. **MSTX打点配置**: + 对关键函数添加MSTX打点,并通过`domain`参数标识打点类别: + + ```python + import torch_npu + + # 打点方式一:标记关键点 + torch_npu.npu.mstx.mark(message=str(num_tokens), domain="generate_tokens") + + # 打点方式二:标记时间段 + mstx_id = torch_npu.npu.mstx.range_start(message="one_dispatch_generate", domain="generate") + out = func(*args, **kwargs) + torch_npu.npu.mstx.range_end(mstx_id) + + # 打点方式三:装饰器方式 + from functools import wraps + + def mstx_timer_decorator(_func=None, *, domain_name="default"): + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + range_id = torch_npu.npu.mstx.range_start(func.__qualname__, domain=domain_name) + result = func(*args, **kwargs) + torch_npu.npu.mstx.range_end(range_id, domain=domain_name) + return result + return wrapper + + if _func is None: + return decorator + else: + return decorator(_func) + + @mstx_timer_decorator(domain="my_function") + def your_function(): + # 函数实现 + pass + ``` + +### 第二步:数据分析 + +#### 命令行使用 + +将所有机器采集的性能数据汇总到`cluster_data`目录后,使用以下命令进行分析: + +```bash +# 输出Jupyter Notebook格式 +msprof-analyze cluster -m rl_analysis -d ./cluster_data -o ./ --export_type notebook + +# 输出数据库格式 +msprof-analyze cluster -m rl_analysis -d ./cluster_data -o ./ --export_type db +``` + +#### 参数说明 + +| 参数 | 说明 | +|------|------| +| `-d` | 集群数据路径 | +| `-o` | 输出目录 | +| `--export_type` | 输出格式(notebook/db) | +| 其他参数 | 详见[参数说明](../../README.md#参数说明) | + +#### 输出文件 + +分析完成后将生成以下文件: + +| 文件名 | 说明 | +|--------|------| +| `rl_event_summary.csv` | 原始MSTX打点事件数据 | +| `rl_event_statistic.xlsx` | 按Roll-Rank-Domain分组的统计数据 | +| `rl_timeline_thumbnail.png` | Timeline缩略图 | +| `stats.ipynb` | 交互式分析文件(设置`--export_type notebook`时)| +| `cluster_anlysis.db` | 原始数据db文件(设置`--export_type db`时)| + + +### 第三步:结果分析与可视化 + +#### 数据文件详解 + +**1. rl_event_summary.csv - mstx打点汇总数据** + +| 字段名称 | 说明 | +|---------|------| +| name | MSTX打点的message信息 | +| roll | 强化学习计算阶段标识 | +| domain | 打点类型标识 | +| start_time_ms | 开始时间(毫秒) | +| end_time_ms | 结束时间(毫秒) | +| duration_ms | 持续时间(毫秒) | +| host_uid | 主机唯一标识 | +| device_id | 设备ID | +| rank_id | 全局rank ID | +| tid | 线程ID | +| communication_group | 通信组rank | + +**2. rl_event_statistic.xlsx - mstx打点统计数据** + +| 字段名称 | 说明 | +|---------|------| +| Roll | 强化学习计算阶段 | +| Rank ID | 全局rank ID | +| Domain | 打点类型 | +| Count | 打点总次数 | +| Total Time(ms) | 总时间 | +| Max Time(ms) | 最大时间 | +| Min Time(ms) | 最小时间 | +| Mean Time(ms) | 平均时间 | + +#### 可视化功能 + +**1. 按Roll-全局Rank分组的timeline缩略图** +- 文件:`rl_timeline_thumbnail.png` +- 内容:按Roll-全局Rank分组的timeline缩略图,如下图所示: +![rl_timeline_thumbnail](../source/img/rl_timeline_thumbnail.png) + +**2. 按Roll-通讯域Rank分组的timeline缩略图** +支持按通信域rank(dp rank/pp rank/tp rank)分组的可视化分析。需要在每份profiling的数据采集区间,通过mstx接口标识该份profiling数据所属的通讯域rank,例如,可以通过以下方式标识数据的dp rank: + +```python +# 在profiler采集区间标识通信域rank,domain需要设置为"communication_group" +torch_npu.npu.mstx.mark(message=f"dp{dp_rank}", domain="communication_group") +``` + +配置完成后,设置`--export_type notebook`,在`stats.ipynb`中可选择按dp、pp、tp汇总数据,生成相应的timeline缩略图。例如,按照dp rank分组的timeline缩略图,如下图所示: +![rl_timeline_thumbnail_by_dp](../source/img/rl_timeline_thumbnail_by_dp.png) + +**3. Jupyter Notebook交互式分析** +- 当设置`--export_type notebook`时生成`stats.ipynb` +- 提供交互式数据分析和可视化功能 + +## 扩展开发指导 + +`rl_analysis`支持用户基于汇总的`rl_event_summary.csv`数据进行自定义分析。 + +### 自定义可视化函数 + +当导出类型为notebook时,可在交付件目录中`cluster_display.py`的`RLAnalysisChart`类中添加自定义画图函数: + +```python +class RLAnalysisChart: + def __init__(self, events_df, selected_domains=None): + # 初始化逻辑 + self.events_summary = events_df + self.selected_domains = selected_domains + + def plot_timeline_thumbnail(self): + # 现有的timeline缩略图绘制函数 + ... + + def plot_custom_analysis(self): + # 自定义分析逻辑 + # 可以访问 self.events_summary 数据 + # 实现自定义的可视化分析 + pass +``` + +### 在Notebook中调用 + +```python +# 在notebook中调用自定义函数 +rl_chart = RLAnalysisChart(rl_events_df) +rl_chart.plot_custom_analysis() +``` + +## 注意事项 + +### 版本要求 +- **CANN包**:需要8.2.RC1或更高版本 +- **FrameworkPTAdapter**:需要7.1.RC1或更高版本 + +### 使用限制 +- 必须使用支持的强化学习框架 +- 需要正确配置MSTX打点 diff --git a/profiler/msprof_analyze/docs/source/img/reinforcement_learning_train.png b/profiler/msprof_analyze/docs/source/img/reinforcement_learning_train.png new file mode 100644 index 0000000000000000000000000000000000000000..4a31bb62f7dbb6a8a87865177600f765e248d649 Binary files /dev/null and b/profiler/msprof_analyze/docs/source/img/reinforcement_learning_train.png differ diff --git a/profiler/msprof_analyze/docs/source/img/rl_timeline_thumbnail.png b/profiler/msprof_analyze/docs/source/img/rl_timeline_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..bf26160c5c67bcb9880d0beb42176610dd1c50ca Binary files /dev/null and b/profiler/msprof_analyze/docs/source/img/rl_timeline_thumbnail.png differ diff --git a/profiler/msprof_analyze/docs/source/img/rl_timeline_thumbnail_by_dp.png b/profiler/msprof_analyze/docs/source/img/rl_timeline_thumbnail_by_dp.png new file mode 100644 index 0000000000000000000000000000000000000000..2b1c3a3fbc1f253e64d5da89762837e1b849747e Binary files /dev/null and b/profiler/msprof_analyze/docs/source/img/rl_timeline_thumbnail_by_dp.png differ diff --git a/profiler/msprof_analyze/prof_common/constant.py b/profiler/msprof_analyze/prof_common/constant.py index 7b9c88e8b01705e36598d24b2d56d7ce6de5c411..c600296ebe5c6d5263cac33bf0f76ebcf6b432eb 100644 --- a/profiler/msprof_analyze/prof_common/constant.py +++ b/profiler/msprof_analyze/prof_common/constant.py @@ -475,7 +475,6 @@ class Constant(object): CONCURRENT_MODE = "concurrent" PROFILER_DB_PATH = "profiler_db_path" ANALYSIS_DB_PATH = "analysis_db_path" - ROLL = "roll" RANK_LIST = "rank_list" EXPORT_TYPE = "export_type" EXTRA_ARGS = "args"