From 9e8de838ee1693c311e376e59794b23136031742 Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Fri, 3 Jan 2025 14:44:39 +0800 Subject: [PATCH 01/11] [profiler]Add cases of profiler --- .../optimize/ms_insight_profiling.md | 46 +++++++++++++++++++ .../model_train/optimize/profiler.md | 4 +- docs/sample_code/profiler/dynamic_profiler.py | 14 +++--- 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md new file mode 100644 index 0000000000..5cc491c3de --- /dev/null +++ b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md @@ -0,0 +1,46 @@ +# MindSpore Insight性能分析 + +## 一、采集性能数据 +在性能分析前需要采集MindSpore性能数据,采集性能数据的方式有三种:mindspore.Profiler接口使能、动态profiler使能、环境变量使能。详细采集数据方式请参考[MindSpore性能数据采集](https://gitee.com/mindspore/docs/tree/master/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md)。 + +## 二、MindSpore Insight性能分析 +MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实软硬件运行数据,多维度分析性能数位,定位性能瓶颈点,支持百卡、千卡及以上规模的可视化集群性能分析。用户在MindStudio Insight中导入上一步采集的性能数据,根据下述流程使用可视化能力分析性能数据。 + +### 1. 概览界面总览数据情况 +可以通过概览界面了解每个模块的具体内容。 +- 首先,在“并行策略分析”模块,数据采用TP-DP-PP的顺序进行编号,用户只需点击复选框选择并行策略,即可通过方框标注识别并行分组。并根据热力图找到存在性能问题的通信域,根据数据类型选择不同的时间指标,越偏向红色表示性能越差。 +- 接下来,可以在计算/通信概览部分展示所选通信域下每张卡的计算、通信、空闲时间占比情况,并提供专家建议。 +各图例相关数据指标的含义如下: + +| 图例 | 含义 | +|--------------|---------| +| 总计算时间 | 昇腾设备上的内核时间总和 | +| 纯计算时间 | 纯计算时间 = 总计算时间 – 通信时间(被覆盖) | +| 通信时间(被覆盖) | 被覆盖的通信时长,即计算和通信同时进行的时长 | +| 通信时间(未被覆盖) | 未被覆盖的通信时长,即纯通信时长 | +| 空闲时间 | 未进行计算或通信的时长 | + +### 2.定界问题 +不同的指标现象可以定界不同的性能问题: +- (1)计算问题:通常表现为通信域中总计算时间占比的极大值和极小值差异过大。如果某些计算卡的计算时间明显超出了正常范围,那很可能意味着这张卡承担了过于繁重的计算任务,比如要处理的数据量过大,或者模型计算的复杂程度过高,也有可能是卡本身的性能受到了限制。 +- (2)调度问题:通常表现为通信域中空闲时间占比的极大值和极小值差异过大。如果计算卡的空闲时间过长,那就说明任务分配可能不太均衡,或者是存在卡之间互相等待数据的情况,这同样会对集群的性能造成不利影响。 +- (3)通信问题:如果通信时间(未被覆盖)过长,那就表明计算和通信之间的协同出现了问题,可能对应多种情况。也许是通信协议不够优化,又或者是网络带宽不稳定,导致通信无法和计算良好配合。 +#### 2.1 计算问题 +当数据指标现象指示为计算问题时,可以直接查看异常卡的算子数据,并与正常卡进行比较。此时可以使用MindStudio Insight的卡间性能比对功能,设置两卡进入比对模式,并在算子界面查看结果。下图是一个存在计算问题的例子,可以看到在算子数量相等的前提下,MatMul算子平均耗时明显增多,造成了两张单卡的计算时间差异。 + +#### 2.2 调度问题 +当数据指标现象指示为调度问题时,需要到时间线界面将异常卡和正常卡进行比较,进一步定位出现问题的算子。进入时间线界面,选择HostToDevice连线类型,HostToDevice展示了CANN层算子到AscendHardware的算子的下发执行关系和CANN层算子到HCCL通信算子的下发执行关系,用于定位调度问题。 +HostToDevice的连线通常有两种形态,倾斜和竖直。下图是一个存在调度问题的案例,如果HostToDevice连线如左侧所示,是倾斜的,说明此时间段调度任务安排合理,昇腾设备是满负荷执行计算和通信任务的。如果HostToDevice连线如右侧所示,是竖直的,说明昇腾设备此时快速执行完了CPU下发的任务,未满负荷进行计算和通信任务,这一般表示存在调度问题。 + +#### 2.3 通信问题 +当数据指标现象指示为通信问题时,需要进入通信界面进一步分析。通信界面用于展示集群中全网链路性能以及所有节点的通信性能,通过集群通信与计算重叠时间的分析可以找出集群训练中的慢主机或慢节点。通常,我们会根据关键指标通信矩阵、通信时长来分析性能问题。 +- 通信矩阵 + +上图是MindStudio Insight通信矩阵可视化界面,可以获取各个通信域下,卡间的带宽、传输大小、链路方式和传输时长情况等信息。 +分析时可以先查看传输大小,分析在这个集合通信中,每张卡的传输量是否存在差异,是否有分配不均的情况。其次,再查看传输时长,如果某张卡的传输时长非常短,那它极有可能是在处理其他事情,导致下游卡长时间等待。最后可以查看带宽情况,如果不同卡间的带宽数据差异过大或带宽数值异常,那都意味着通信域中存在异常卡。 + +- 通信时长 + +通信时长是指计算卡之间进行一次通信所花费的时间。导致通信耗时过长的因素很多,比如通信协议配置错误、传输数据量过大等等,只有找到这些通信耗时过长的链路并妥善解决问题,才能让数据在计算卡之间更加顺畅地传输,进而提高集群的整体性能。 +用户选择具体通信域后,即可在通信时长界面中查看通信域中各个计算卡的耗时汇总情况,以及每个通信算子的时序图和通信时长的分布图,从而快速获得通信算子的相对位置关系以及详细通信数据。 + diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md index 3e80d82133..e2182393fe 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md @@ -29,7 +29,6 @@ **Graph**模式下,用户可以通过Callback方式来使能Profiler。 ```python -import os import mindspore as ms from mindspore import Profiler @@ -324,6 +323,9 @@ MindSpore Profiler接口将框架侧的数据与CANN Profling的数据关联整 其他性能数据文件的具体字段与含义可以参考[昇腾官网文档](https://www.hiascend.com/document/detail/zh/mindstudio/70RC3/T&ITools/Profiling/atlasprofiling_16_0035.html)。 +## 性能问题分析 +基于MindStudio Insight性能调优分析详细流程请参考[MindSpore Insight性能调优分析]()。 + ## 常见工具问题及解决办法 ### 使用step采集性能数据常见问题 diff --git a/docs/sample_code/profiler/dynamic_profiler.py b/docs/sample_code/profiler/dynamic_profiler.py index ee70a1c5fe..18d7363bea 100644 --- a/docs/sample_code/profiler/dynamic_profiler.py +++ b/docs/sample_code/profiler/dynamic_profiler.py @@ -61,13 +61,13 @@ if __name__ == '__main__': cfg_json = { "start_step": 2, "stop_step": 5, - "aicore_metrics": 1, - "profiler_level": -1, - "profile_framework": 1, - "analyse_mode": 0, - "with_stack": True, - "parallel_strategy": True, - "data_simplification": False, + "aicore_metrics": -1, + "profiler_level": 0, + "activities": 0, + "analyse_mode": -1, + "with_stack": False, + "parallel_strategy": False, + "data_simplification": True, } context.set_context(mode=mindspore.PYNATIVE_MODE) mindspore.set_device("Ascend") -- Gitee From 8f905f3b170aeed65849885ecde23808032e9be1 Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Fri, 3 Jan 2025 14:59:12 +0800 Subject: [PATCH 02/11] [profiler]Add cases of profiler --- .../model_train/optimize/ms_insight_profiling.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md index 5cc491c3de..c32d67743d 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md @@ -2,10 +2,8 @@ ## 一、采集性能数据 在性能分析前需要采集MindSpore性能数据,采集性能数据的方式有三种:mindspore.Profiler接口使能、动态profiler使能、环境变量使能。详细采集数据方式请参考[MindSpore性能数据采集](https://gitee.com/mindspore/docs/tree/master/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md)。 - ## 二、MindSpore Insight性能分析 MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实软硬件运行数据,多维度分析性能数位,定位性能瓶颈点,支持百卡、千卡及以上规模的可视化集群性能分析。用户在MindStudio Insight中导入上一步采集的性能数据,根据下述流程使用可视化能力分析性能数据。 - ### 1. 概览界面总览数据情况 可以通过概览界面了解每个模块的具体内容。 - 首先,在“并行策略分析”模块,数据采用TP-DP-PP的顺序进行编号,用户只需点击复选框选择并行策略,即可通过方框标注识别并行分组。并根据热力图找到存在性能问题的通信域,根据数据类型选择不同的时间指标,越偏向红色表示性能越差。 @@ -27,20 +25,16 @@ MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实 - (3)通信问题:如果通信时间(未被覆盖)过长,那就表明计算和通信之间的协同出现了问题,可能对应多种情况。也许是通信协议不够优化,又或者是网络带宽不稳定,导致通信无法和计算良好配合。 #### 2.1 计算问题 当数据指标现象指示为计算问题时,可以直接查看异常卡的算子数据,并与正常卡进行比较。此时可以使用MindStudio Insight的卡间性能比对功能,设置两卡进入比对模式,并在算子界面查看结果。下图是一个存在计算问题的例子,可以看到在算子数量相等的前提下,MatMul算子平均耗时明显增多,造成了两张单卡的计算时间差异。 - #### 2.2 调度问题 当数据指标现象指示为调度问题时,需要到时间线界面将异常卡和正常卡进行比较,进一步定位出现问题的算子。进入时间线界面,选择HostToDevice连线类型,HostToDevice展示了CANN层算子到AscendHardware的算子的下发执行关系和CANN层算子到HCCL通信算子的下发执行关系,用于定位调度问题。 HostToDevice的连线通常有两种形态,倾斜和竖直。下图是一个存在调度问题的案例,如果HostToDevice连线如左侧所示,是倾斜的,说明此时间段调度任务安排合理,昇腾设备是满负荷执行计算和通信任务的。如果HostToDevice连线如右侧所示,是竖直的,说明昇腾设备此时快速执行完了CPU下发的任务,未满负荷进行计算和通信任务,这一般表示存在调度问题。 - #### 2.3 通信问题 当数据指标现象指示为通信问题时,需要进入通信界面进一步分析。通信界面用于展示集群中全网链路性能以及所有节点的通信性能,通过集群通信与计算重叠时间的分析可以找出集群训练中的慢主机或慢节点。通常,我们会根据关键指标通信矩阵、通信时长来分析性能问题。 - 通信矩阵 - 上图是MindStudio Insight通信矩阵可视化界面,可以获取各个通信域下,卡间的带宽、传输大小、链路方式和传输时长情况等信息。 分析时可以先查看传输大小,分析在这个集合通信中,每张卡的传输量是否存在差异,是否有分配不均的情况。其次,再查看传输时长,如果某张卡的传输时长非常短,那它极有可能是在处理其他事情,导致下游卡长时间等待。最后可以查看带宽情况,如果不同卡间的带宽数据差异过大或带宽数值异常,那都意味着通信域中存在异常卡。 - 通信时长 - 通信时长是指计算卡之间进行一次通信所花费的时间。导致通信耗时过长的因素很多,比如通信协议配置错误、传输数据量过大等等,只有找到这些通信耗时过长的链路并妥善解决问题,才能让数据在计算卡之间更加顺畅地传输,进而提高集群的整体性能。 用户选择具体通信域后,即可在通信时长界面中查看通信域中各个计算卡的耗时汇总情况,以及每个通信算子的时序图和通信时长的分布图,从而快速获得通信算子的相对位置关系以及详细通信数据。 -- Gitee From b015cd11066689e3d857ac738a82d8a36c06ff74 Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Fri, 3 Jan 2025 16:46:48 +0800 Subject: [PATCH 03/11] [profiler]Add cases of profiler --- .../model_train/optimize/ms_insight_profiling.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md index c32d67743d..6412608f57 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md @@ -6,8 +6,9 @@ MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实软硬件运行数据,多维度分析性能数位,定位性能瓶颈点,支持百卡、千卡及以上规模的可视化集群性能分析。用户在MindStudio Insight中导入上一步采集的性能数据,根据下述流程使用可视化能力分析性能数据。 ### 1. 概览界面总览数据情况 可以通过概览界面了解每个模块的具体内容。 -- 首先,在“并行策略分析”模块,数据采用TP-DP-PP的顺序进行编号,用户只需点击复选框选择并行策略,即可通过方框标注识别并行分组。并根据热力图找到存在性能问题的通信域,根据数据类型选择不同的时间指标,越偏向红色表示性能越差。 -- 接下来,可以在计算/通信概览部分展示所选通信域下每张卡的计算、通信、空闲时间占比情况,并提供专家建议。 +- 首先,在MindStudio Insight界面中选择'导入数据'按钮,导入采集的profiler数据,以下导入为多卡的性能数据,如下图所示。 +在时间线界面可以看出导入了8卡数据,如下图。 +- 接下来,可以在概览部分展示所选通信域下每张卡的计算、通信、空闲时间占比情况,并提供专家建议。 各图例相关数据指标的含义如下: | 图例 | 含义 | @@ -24,7 +25,7 @@ MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实 - (2)调度问题:通常表现为通信域中空闲时间占比的极大值和极小值差异过大。如果计算卡的空闲时间过长,那就说明任务分配可能不太均衡,或者是存在卡之间互相等待数据的情况,这同样会对集群的性能造成不利影响。 - (3)通信问题:如果通信时间(未被覆盖)过长,那就表明计算和通信之间的协同出现了问题,可能对应多种情况。也许是通信协议不够优化,又或者是网络带宽不稳定,导致通信无法和计算良好配合。 #### 2.1 计算问题 -当数据指标现象指示为计算问题时,可以直接查看异常卡的算子数据,并与正常卡进行比较。此时可以使用MindStudio Insight的卡间性能比对功能,设置两卡进入比对模式,并在算子界面查看结果。下图是一个存在计算问题的例子,可以看到在算子数量相等的前提下,MatMul算子平均耗时明显增多,造成了两张单卡的计算时间差异。 +当数据指标现象指示为计算问题时,可以直接查看异常卡的算子数据,并与正常卡进行比较。此时可以使用MindStudio Insight的卡间性能比对功能,设置两卡进入比对模式,并在算子界面查看结果。其中饼状图展示了各类算子的耗时占比,表格展示了各类算子的详细信息。 #### 2.2 调度问题 当数据指标现象指示为调度问题时,需要到时间线界面将异常卡和正常卡进行比较,进一步定位出现问题的算子。进入时间线界面,选择HostToDevice连线类型,HostToDevice展示了CANN层算子到AscendHardware的算子的下发执行关系和CANN层算子到HCCL通信算子的下发执行关系,用于定位调度问题。 HostToDevice的连线通常有两种形态,倾斜和竖直。下图是一个存在调度问题的案例,如果HostToDevice连线如左侧所示,是倾斜的,说明此时间段调度任务安排合理,昇腾设备是满负荷执行计算和通信任务的。如果HostToDevice连线如右侧所示,是竖直的,说明昇腾设备此时快速执行完了CPU下发的任务,未满负荷进行计算和通信任务,这一般表示存在调度问题。 -- Gitee From 50aef33cdbf9dfc47683ff33585effa7a1f7032b Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Fri, 3 Jan 2025 17:04:09 +0800 Subject: [PATCH 04/11] [profiler]Add cases of profiler --- docs/mindspore/source_zh_cn/model_train/optimize/profiler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md index e2182393fe..1e4a31149d 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md @@ -324,7 +324,7 @@ MindSpore Profiler接口将框架侧的数据与CANN Profling的数据关联整 其他性能数据文件的具体字段与含义可以参考[昇腾官网文档](https://www.hiascend.com/document/detail/zh/mindstudio/70RC3/T&ITools/Profiling/atlasprofiling_16_0035.html)。 ## 性能问题分析 -基于MindStudio Insight性能调优分析详细流程请参考[MindSpore Insight性能调优分析]()。 +基于MindStudio Insight性能调优分析详细流程请参考[MindSpore Insight性能调优分析](./ms_insight_profiling.md)。 ## 常见工具问题及解决办法 -- Gitee From 100d55ee88d20072be6a5bde6484a1aece45a78b Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Mon, 6 Jan 2025 16:35:26 +0800 Subject: [PATCH 05/11] [profiler]Add cases of profiler --- .../optimize/images/profiler_process.png | Bin 0 -> 49216 bytes .../optimize/ms_insight_profiling.md | 14 ++++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 docs/mindspore/source_zh_cn/model_train/optimize/images/profiler_process.png diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/images/profiler_process.png b/docs/mindspore/source_zh_cn/model_train/optimize/images/profiler_process.png new file mode 100644 index 0000000000000000000000000000000000000000..479480c298970c29d65702ccbd1f7fd19bfd3ce6 GIT binary patch literal 49216 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 JJbf|ze*h>JRD%Ej literal 0 HcmV?d00001 diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md index 6412608f57..2bce7d565f 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md @@ -1,8 +1,14 @@ # MindSpore Insight性能分析 - -## 一、采集性能数据 -在性能分析前需要采集MindSpore性能数据,采集性能数据的方式有三种:mindspore.Profiler接口使能、动态profiler使能、环境变量使能。详细采集数据方式请参考[MindSpore性能数据采集](https://gitee.com/mindspore/docs/tree/master/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md)。 -## 二、MindSpore Insight性能分析 +## 一、概述 +在大模型训练过程中,由于一些不可预知的引入,导致模型出现了一些性能劣化的问题,例如算子计算时间慢、通信快慢卡等。需要定位性能劣化的根本原因,并解决问题。 +## 二、性能问题定位流程 +![profiler_process.png](images%2Fprofiler_process.png) +性能调优最重要的就是对症下药,先定界问题,再对问题进行针对性优化。 +首先进行性能数据采集,可以使用MindSpore Profiler提供的接口进行数据采集和解析。接下来,使用MindStudio Insight可视化工具定界性能问题,定界结果通常分为计算、调度、通信三个方向的问题。最后,用户可以根据MindStudio Insight专家建议进行性能调优, +每次调优后重跑训练,采集性能数据,并使用[MindStudio Insight](https://www.mindspore.cn/mindinsight/docs/zh-CN/master/index.html)可视化工具查看调优手段是否产生效果。重复这个过程,直到解决性能问题。 +## 三、采集性能数据 +采集性能数据的方式有三种:mindspore.Profiler接口使能、动态profiler使能、环境变量使能。详细采集数据方式请参考[MindSpore性能数据采集](https://www.mindspore.cn/docs/zh-CN/r2.4.1/model_train/optimize/profiler.html)。 +## 四、MindSpore Insight性能分析 MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实软硬件运行数据,多维度分析性能数位,定位性能瓶颈点,支持百卡、千卡及以上规模的可视化集群性能分析。用户在MindStudio Insight中导入上一步采集的性能数据,根据下述流程使用可视化能力分析性能数据。 ### 1. 概览界面总览数据情况 可以通过概览界面了解每个模块的具体内容。 -- Gitee From 7494405fccf45d4a9e7e29cbe18876f1eec3316a Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Mon, 6 Jan 2025 16:37:22 +0800 Subject: [PATCH 06/11] [profiler]Add cases of profiler --- .../source_zh_cn/model_train/optimize/ms_insight_profiling.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md index 2bce7d565f..ce64129048 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md @@ -2,7 +2,9 @@ ## 一、概述 在大模型训练过程中,由于一些不可预知的引入,导致模型出现了一些性能劣化的问题,例如算子计算时间慢、通信快慢卡等。需要定位性能劣化的根本原因,并解决问题。 ## 二、性能问题定位流程 + ![profiler_process.png](images%2Fprofiler_process.png) + 性能调优最重要的就是对症下药,先定界问题,再对问题进行针对性优化。 首先进行性能数据采集,可以使用MindSpore Profiler提供的接口进行数据采集和解析。接下来,使用MindStudio Insight可视化工具定界性能问题,定界结果通常分为计算、调度、通信三个方向的问题。最后,用户可以根据MindStudio Insight专家建议进行性能调优, 每次调优后重跑训练,采集性能数据,并使用[MindStudio Insight](https://www.mindspore.cn/mindinsight/docs/zh-CN/master/index.html)可视化工具查看调优手段是否产生效果。重复这个过程,直到解决性能问题。 -- Gitee From e70f6a98e3321de544eb3f84853ae29b4f719ff7 Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Mon, 6 Jan 2025 16:40:50 +0800 Subject: [PATCH 07/11] [profiler]Add cases of profiler --- .../source_zh_cn/model_train/optimize/ms_insight_profiling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md index ce64129048..17183c395c 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md @@ -16,7 +16,7 @@ MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实 可以通过概览界面了解每个模块的具体内容。 - 首先,在MindStudio Insight界面中选择'导入数据'按钮,导入采集的profiler数据,以下导入为多卡的性能数据,如下图所示。 在时间线界面可以看出导入了8卡数据,如下图。 -- 接下来,可以在概览部分展示所选通信域下每张卡的计算、通信、空闲时间占比情况,并提供专家建议。 +- 接下来,可以在概览界面展示所选通信域下每张卡的计算、通信、空闲时间占比情况,并提供专家建议。 各图例相关数据指标的含义如下: | 图例 | 含义 | -- Gitee From 87d284598176ba0e66393f54f49240ca5e604b7a Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Mon, 6 Jan 2025 16:42:19 +0800 Subject: [PATCH 08/11] [profiler]Add cases of profiler --- .../source_zh_cn/model_train/optimize/ms_insight_profiling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md index 17183c395c..92dfdcd02e 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md @@ -1,4 +1,4 @@ -# MindSpore Insight性能分析 +# MindSpore Insight性能问题定位、分析 ## 一、概述 在大模型训练过程中,由于一些不可预知的引入,导致模型出现了一些性能劣化的问题,例如算子计算时间慢、通信快慢卡等。需要定位性能劣化的根本原因,并解决问题。 ## 二、性能问题定位流程 -- Gitee From 0c4f101ffc609d41697406694ed0165720c3aad4 Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Mon, 6 Jan 2025 17:04:57 +0800 Subject: [PATCH 09/11] [profiler]Add cases of profiler --- .../optimize/ms_insight_profiling.md | 49 ------------------- .../model_train/optimize/profiler.md | 45 +++++++++++++++-- 2 files changed, 42 insertions(+), 52 deletions(-) delete mode 100644 docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md b/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md deleted file mode 100644 index 92dfdcd02e..0000000000 --- a/docs/mindspore/source_zh_cn/model_train/optimize/ms_insight_profiling.md +++ /dev/null @@ -1,49 +0,0 @@ -# MindSpore Insight性能问题定位、分析 -## 一、概述 -在大模型训练过程中,由于一些不可预知的引入,导致模型出现了一些性能劣化的问题,例如算子计算时间慢、通信快慢卡等。需要定位性能劣化的根本原因,并解决问题。 -## 二、性能问题定位流程 - -![profiler_process.png](images%2Fprofiler_process.png) - -性能调优最重要的就是对症下药,先定界问题,再对问题进行针对性优化。 -首先进行性能数据采集,可以使用MindSpore Profiler提供的接口进行数据采集和解析。接下来,使用MindStudio Insight可视化工具定界性能问题,定界结果通常分为计算、调度、通信三个方向的问题。最后,用户可以根据MindStudio Insight专家建议进行性能调优, -每次调优后重跑训练,采集性能数据,并使用[MindStudio Insight](https://www.mindspore.cn/mindinsight/docs/zh-CN/master/index.html)可视化工具查看调优手段是否产生效果。重复这个过程,直到解决性能问题。 -## 三、采集性能数据 -采集性能数据的方式有三种:mindspore.Profiler接口使能、动态profiler使能、环境变量使能。详细采集数据方式请参考[MindSpore性能数据采集](https://www.mindspore.cn/docs/zh-CN/r2.4.1/model_train/optimize/profiler.html)。 -## 四、MindSpore Insight性能分析 -MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实软硬件运行数据,多维度分析性能数位,定位性能瓶颈点,支持百卡、千卡及以上规模的可视化集群性能分析。用户在MindStudio Insight中导入上一步采集的性能数据,根据下述流程使用可视化能力分析性能数据。 -### 1. 概览界面总览数据情况 -可以通过概览界面了解每个模块的具体内容。 -- 首先,在MindStudio Insight界面中选择'导入数据'按钮,导入采集的profiler数据,以下导入为多卡的性能数据,如下图所示。 -在时间线界面可以看出导入了8卡数据,如下图。 -- 接下来,可以在概览界面展示所选通信域下每张卡的计算、通信、空闲时间占比情况,并提供专家建议。 -各图例相关数据指标的含义如下: - -| 图例 | 含义 | -|--------------|---------| -| 总计算时间 | 昇腾设备上的内核时间总和 | -| 纯计算时间 | 纯计算时间 = 总计算时间 – 通信时间(被覆盖) | -| 通信时间(被覆盖) | 被覆盖的通信时长,即计算和通信同时进行的时长 | -| 通信时间(未被覆盖) | 未被覆盖的通信时长,即纯通信时长 | -| 空闲时间 | 未进行计算或通信的时长 | - -### 2.定界问题 -不同的指标现象可以定界不同的性能问题: -- (1)计算问题:通常表现为通信域中总计算时间占比的极大值和极小值差异过大。如果某些计算卡的计算时间明显超出了正常范围,那很可能意味着这张卡承担了过于繁重的计算任务,比如要处理的数据量过大,或者模型计算的复杂程度过高,也有可能是卡本身的性能受到了限制。 -- (2)调度问题:通常表现为通信域中空闲时间占比的极大值和极小值差异过大。如果计算卡的空闲时间过长,那就说明任务分配可能不太均衡,或者是存在卡之间互相等待数据的情况,这同样会对集群的性能造成不利影响。 -- (3)通信问题:如果通信时间(未被覆盖)过长,那就表明计算和通信之间的协同出现了问题,可能对应多种情况。也许是通信协议不够优化,又或者是网络带宽不稳定,导致通信无法和计算良好配合。 -#### 2.1 计算问题 -当数据指标现象指示为计算问题时,可以直接查看异常卡的算子数据,并与正常卡进行比较。此时可以使用MindStudio Insight的卡间性能比对功能,设置两卡进入比对模式,并在算子界面查看结果。其中饼状图展示了各类算子的耗时占比,表格展示了各类算子的详细信息。 -#### 2.2 调度问题 -当数据指标现象指示为调度问题时,需要到时间线界面将异常卡和正常卡进行比较,进一步定位出现问题的算子。进入时间线界面,选择HostToDevice连线类型,HostToDevice展示了CANN层算子到AscendHardware的算子的下发执行关系和CANN层算子到HCCL通信算子的下发执行关系,用于定位调度问题。 -HostToDevice的连线通常有两种形态,倾斜和竖直。下图是一个存在调度问题的案例,如果HostToDevice连线如左侧所示,是倾斜的,说明此时间段调度任务安排合理,昇腾设备是满负荷执行计算和通信任务的。如果HostToDevice连线如右侧所示,是竖直的,说明昇腾设备此时快速执行完了CPU下发的任务,未满负荷进行计算和通信任务,这一般表示存在调度问题。 -#### 2.3 通信问题 -当数据指标现象指示为通信问题时,需要进入通信界面进一步分析。通信界面用于展示集群中全网链路性能以及所有节点的通信性能,通过集群通信与计算重叠时间的分析可以找出集群训练中的慢主机或慢节点。通常,我们会根据关键指标通信矩阵、通信时长来分析性能问题。 -- 通信矩阵 -上图是MindStudio Insight通信矩阵可视化界面,可以获取各个通信域下,卡间的带宽、传输大小、链路方式和传输时长情况等信息。 -分析时可以先查看传输大小,分析在这个集合通信中,每张卡的传输量是否存在差异,是否有分配不均的情况。其次,再查看传输时长,如果某张卡的传输时长非常短,那它极有可能是在处理其他事情,导致下游卡长时间等待。最后可以查看带宽情况,如果不同卡间的带宽数据差异过大或带宽数值异常,那都意味着通信域中存在异常卡。 - -- 通信时长 -通信时长是指计算卡之间进行一次通信所花费的时间。导致通信耗时过长的因素很多,比如通信协议配置错误、传输数据量过大等等,只有找到这些通信耗时过长的链路并妥善解决问题,才能让数据在计算卡之间更加顺畅地传输,进而提高集群的整体性能。 -用户选择具体通信域后,即可在通信时长界面中查看通信域中各个计算卡的耗时汇总情况,以及每个通信算子的时序图和通信时长的分布图,从而快速获得通信算子的相对位置关系以及详细通信数据。 - diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md index 1e4a31149d..53b5c61e2a 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md @@ -323,9 +323,48 @@ MindSpore Profiler接口将框架侧的数据与CANN Profling的数据关联整 其他性能数据文件的具体字段与含义可以参考[昇腾官网文档](https://www.hiascend.com/document/detail/zh/mindstudio/70RC3/T&ITools/Profiling/atlasprofiling_16_0035.html)。 -## 性能问题分析 -基于MindStudio Insight性能调优分析详细流程请参考[MindSpore Insight性能调优分析](./ms_insight_profiling.md)。 - +## 性能分析、调优 +### 一、概述 +在大模型训练过程中,由于一些不可预知的引入,导致模型出现了一些性能劣化的问题,例如算子计算时间慢、通信快慢卡等。需要定位性能劣化的根本原因,并解决问题。 +![profiler_process.png](images%2Fprofiler_process.png) +性能调优最重要的就是对症下药,先定界问题,再对问题进行针对性调优。 +首先使用[MindStudio Insight](https://www.mindspore.cn/mindinsight/docs/zh-CN/master/index.html)可视化工具定界性能问题,定界结果通常分为计算、调度、通信三个方向的问题。最后,用户可以根据MindStudio Insight专家建议进行性能调优, +每次调优后重跑训练,采集性能数据,并使用MindStudio Insight工具查看调优手段是否产生效果。重复这个过程,直到解决性能问题。 +### 二、性能调优 +MindStudio Insight提供了丰富的调优分析手段,可视化呈现真实软硬件运行数据,多维度分析性能数位,定位性能瓶颈点,支持百卡、千卡及以上规模的可视化集群性能分析。用户在MindStudio Insight中导入上一步采集的性能数据,根据下述流程使用可视化能力分析性能数据。 +### 1. 概览界面总览数据情况 +可以通过概览界面了解每个模块的具体内容。 +- 首先,在MindStudio Insight界面中选择'导入数据'按钮,导入采集的profiler数据,以下导入为多卡的性能数据。同时可以在时间线界面看出导入了8卡数据,如下图。 +- 接下来,可以在概览界面展示所选通信域下每张卡的计算、通信、空闲时间占比情况,并提供专家建议。 +各图例相关数据指标的含义如下: + +| 图例 | 含义 | +|--------------|---------| +| 总计算时间 | 昇腾设备上的内核时间总和 | +| 纯计算时间 | 纯计算时间 = 总计算时间 – 通信时间(被覆盖) | +| 通信时间(被覆盖) | 被覆盖的通信时长,即计算和通信同时进行的时长 | +| 通信时间(未被覆盖) | 未被覆盖的通信时长,即纯通信时长 | +| 空闲时间 | 未进行计算或通信的时长 | + +### 2. 定界问题 +不同的指标现象可以定界不同的性能问题: +- (1)计算问题:通常表现为通信域中总计算时间占比的极大值和极小值差异过大。如果某些计算卡的计算时间明显超出了正常范围,那很可能意味着这张卡承担了过于繁重的计算任务,比如要处理的数据量过大,或者模型计算的复杂程度过高,也有可能是卡本身的性能受到了限制。 +- (2)调度问题:通常表现为通信域中空闲时间占比的极大值和极小值差异过大。如果计算卡的空闲时间过长,那就说明任务分配可能不太均衡,或者是存在卡之间互相等待数据的情况,这同样会对集群的性能造成不利影响。 +- (3)通信问题:如果通信时间(未被覆盖)过长,那就表明计算和通信之间的协同出现了问题,可能对应多种情况。也许是通信协议不够优化,又或者是网络带宽不稳定,导致通信无法和计算良好配合。 +#### 2.1 计算问题 +当数据指标现象指示为计算问题时,可以直接查看异常卡的算子数据,并与正常卡进行比较。此时可以使用MindStudio Insight的卡间性能比对功能,设置两卡进入比对模式,并在算子界面查看结果。其中饼状图展示了各类算子的耗时占比,表格展示了各类算子的详细信息。 +#### 2.2 调度问题 +当数据指标现象指示为调度问题时,需要到时间线界面将异常卡和正常卡进行比较,进一步定位出现问题的算子。进入时间线界面,选择HostToDevice连线类型,HostToDevice展示了CANN层算子到AscendHardware的算子的下发执行关系和CANN层算子到HCCL通信算子的下发执行关系,用于定位调度问题。 +HostToDevice的连线通常有两种形态,倾斜和竖直。下图是一个存在调度问题的案例,如果HostToDevice连线如左侧所示,是倾斜的,说明此时间段调度任务安排合理,昇腾设备是满负荷执行计算和通信任务的。如果HostToDevice连线如右侧所示,是竖直的,说明昇腾设备此时快速执行完了CPU下发的任务,未满负荷进行计算和通信任务,这一般表示存在调度问题。 +#### 2.3 通信问题 +当数据指标现象指示为通信问题时,需要进入通信界面进一步分析。通信界面用于展示集群中全网链路性能以及所有节点的通信性能,通过集群通信与计算重叠时间的分析可以找出集群训练中的慢主机或慢节点。通常,我们会根据关键指标通信矩阵、通信时长来分析性能问题。 +- 通信矩阵 +上图是MindStudio Insight通信矩阵可视化界面,可以获取各个通信域下,卡间的带宽、传输大小、链路方式和传输时长情况等信息。 +分析时可以先查看传输大小,分析在这个集合通信中,每张卡的传输量是否存在差异,是否有分配不均的情况。其次,再查看传输时长,如果某张卡的传输时长非常短,那它极有可能是在处理其他事情,导致下游卡长时间等待。最后可以查看带宽情况,如果不同卡间的带宽数据差异过大或带宽数值异常,那都意味着通信域中存在异常卡。 + +- 通信时长 +通信时长是指计算卡之间进行一次通信所花费的时间。导致通信耗时过长的因素很多,比如通信协议配置错误、传输数据量过大等等,只有找到这些通信耗时过长的链路并妥善解决问题,才能让数据在计算卡之间更加顺畅地传输,进而提高集群的整体性能。 +用户选择具体通信域后,即可在通信时长界面中查看通信域中各个计算卡的耗时汇总情况,以及每个通信算子的时序图和通信时长的分布图,从而快速获得通信算子的相对位置关系以及详细通信数据。 ## 常见工具问题及解决办法 ### 使用step采集性能数据常见问题 -- Gitee From dd79f036810b5ad38e50fa7c384edb190fbecb0f Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Mon, 6 Jan 2025 17:06:07 +0800 Subject: [PATCH 10/11] [profiler]Add cases of profiler --- docs/mindspore/source_zh_cn/model_train/optimize/profiler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md index 53b5c61e2a..522fa35ccf 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md @@ -323,7 +323,7 @@ MindSpore Profiler接口将框架侧的数据与CANN Profling的数据关联整 其他性能数据文件的具体字段与含义可以参考[昇腾官网文档](https://www.hiascend.com/document/detail/zh/mindstudio/70RC3/T&ITools/Profiling/atlasprofiling_16_0035.html)。 -## 性能分析、调优 +## 性能调优案例 ### 一、概述 在大模型训练过程中,由于一些不可预知的引入,导致模型出现了一些性能劣化的问题,例如算子计算时间慢、通信快慢卡等。需要定位性能劣化的根本原因,并解决问题。 ![profiler_process.png](images%2Fprofiler_process.png) -- Gitee From 73619e32b161fa1b9a4ef1a36949736178b79656 Mon Sep 17 00:00:00 2001 From: yuliangbin Date: Mon, 6 Jan 2025 17:07:45 +0800 Subject: [PATCH 11/11] [profiler]Add cases of profiler --- docs/mindspore/source_zh_cn/model_train/optimize/profiler.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md index 522fa35ccf..e5f63c7219 100644 --- a/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md +++ b/docs/mindspore/source_zh_cn/model_train/optimize/profiler.md @@ -326,7 +326,9 @@ MindSpore Profiler接口将框架侧的数据与CANN Profling的数据关联整 ## 性能调优案例 ### 一、概述 在大模型训练过程中,由于一些不可预知的引入,导致模型出现了一些性能劣化的问题,例如算子计算时间慢、通信快慢卡等。需要定位性能劣化的根本原因,并解决问题。 + ![profiler_process.png](images%2Fprofiler_process.png) + 性能调优最重要的就是对症下药,先定界问题,再对问题进行针对性调优。 首先使用[MindStudio Insight](https://www.mindspore.cn/mindinsight/docs/zh-CN/master/index.html)可视化工具定界性能问题,定界结果通常分为计算、调度、通信三个方向的问题。最后,用户可以根据MindStudio Insight专家建议进行性能调优, 每次调优后重跑训练,采集性能数据,并使用MindStudio Insight工具查看调优手段是否产生效果。重复这个过程,直到解决性能问题。 -- Gitee