compare_tools(性能比对工具)支持比较GPU与NPU之间、NPU与NPU之间的性能差异,通过对训练耗时和内存占用的比对分析,定位到具体劣化的算子,帮助用户提升性能调优的效率。工具将训练耗时拆分为计算、通信、调度三大维度,并针对计算和通信分别进行算子级别的比对;将训练占用的总内存,拆分成算子级别的内存占用进行比对。
场景一:PyTorch训练工程从GPU迁移至NPU后出现性能劣化,通过工具分析出劣化点。
场景二:PyTorch或MindSpore训练工程在NPU上,不同版本之间存在性能差距,通过工具定位具体差异。
场景三:PyTorch训练工程从GPU迁移至MindSpore NPU后出现性能劣化,通过工具分析出劣化点。
使用本工具前需要安装的依赖包:
pip3 install prettytable
pip3 install xlsxwriter
pip3 install pandas
pip3 install numpy
使用本工具之前需要采集GPU或者NPU的性能数据,建议只采集一个step的性能数据,然后进行性能比对分析。
通过PyTorch Profiler工具采集GPU的性能数据,参考链接:torch.profiler。
采集样例代码参考一:
with torch.profiler.profile(
profile_memory=True, # 内存数据采集的开关
record_shapes=True, # 算子input shape信息采集的开关
schedule=torch.profiler.schedule(wait=10, warmup=0, active=1, repeat=1),
on_trace_ready=torch.profiler.tensorboard_trace_handler("./result_dir")
) as prof:
for step in ranges(step_number):
train_one_step()
prof.step()
采集样例代码参考二:
prof = torch.profiler.profile(
profile_memory=True, # 内存数据采集的开关
record_shapes=True, # 算子input shape信息采集的开关
on_trace_ready=torch.profiler.tensorboard_trace_handler("./result_dir"))
for step in range(step_number):
if step == 11:
prof.start()
train_one_step()
if step == 11:
prof.stop()
PyTorch Profiler采集结果数据目录结构如下:
|- pytorch_profiling
|- *.pt.trace.json
通过Ascend PyTorch Profiler工具采集NPU的性能数据,采集参数配置与GPU基本一致,只需将GPU的性能数据采集代码中torch.profiler替换成torch_npu.profiler。,参考链接:Profiling数据采集。
Ascend PyTorch Profiler采集结果数据目录结构如下:
|- ascend_pytorch_profiling
|- * _ascend_pt
|- ASCEND_PROFILER_OUTPUT
|- kernel_details.csv
|- trace_view.json
|- FRAMEWORK
|- PROF_XXX
|- * _ascend_pt
当前MindSpore场景仅支持NPU环境性能数据与PyTorch GPU性能数据进行比对;以及MindSpore训练工程在NPU上,不同版本之间的性能数据进行比对。
通过MindSpore性能调试工具采集NPU的性能数据,建议只采集或只解析一个step的性能数据,参考链接:性能调试(Ascend)。
MindSpore性能调试工具采集结果数据目录结构如下:
|- profiler/{rank-*}_{timestamps}_ascend_ms
|- ASCEND_PROFILER_OUTPUT
|- kernel_details.csv
|- trace_view.json
进行性能比对时,MindSpore采集的性能数据须指定到profiler/{rank-*}_{timestamps}_ascend_ms
或ASCEND_PROFILER_OUTPUT
层级。
性能比对工具将总体性能拆解为训练耗时和内存占用,其中训练耗时可拆分为算子(包括算子和nn.Module)、通信、调度三个维度,以打屏的形式输出总体指标,帮助用户定界劣化的方向。与此同时,工具还会生成performance_comparison_result_{timestamp}.xlsx,展示每个算子在执行耗时、通信耗时、内存占用的优劣,可通过DIFF列大于0筛选出劣化算子。详细介绍请参见“比对结果说明”。
性能比对工具支持使用命令行和脚本两种方式执行性能数据比对操作,这两种方式均支持通用参数和算子性能比对特有参数。
参见《性能工具》完成工具安装。
执行如下命令进行性能数据比对:
msprof-analyze compare -d [比对性能数据文件所在路径] -bp [基准性能数据文件所在路径] --output_path=[比对结果文件存放路径]
将mstt代码仓下载到本地,执行如下命令:
# 进入mstt代码仓目录下的compare_tools目录
cd mstt/profiler/compare_tools
# 执行最简比对命令
python performance_compare.py [基准性能数据文件所在路径] [比对性能数据文件所在路径] --output_path=[比对结果文件存放路径]
参数名 | 说明 | 是否必选 |
---|---|---|
--enable_profiling_compare | 开启总体性能比对。 | 否 |
--enable_operator_compare | 开启算子性能比对。MindSpore场景暂不支持。该开关较耗时,建议只采集一个step的性能数据。 | 否 |
--enable_communication_compare | 开启通信性能比对。 | 否 |
--enable_memory_compare | 开启算子内存比对。MindSpore场景暂不支持。该开关较耗时,建议只采集一个step的性能数据。 | 否 |
--enable_kernel_compare | 开启kernel性能比对。仅针对NPU与NPU比对的场景。需要使用性能数据中的kernel_details.csv文件。 | 否 |
--enable_api_compare | 开启API性能比对。需要使用性能数据中的trace_view.csv文件。 | 否 |
--disable_details | 隐藏明细比对,只进行统计级比对。 | 否 |
--base_step | 基准性能数据step ID,配置后使用基准性能数据对应step的数据进行比对。为整数,需配置实际数据存在的step ID,默认未配置,比对所有性能数据,需要与--comparison_step同时配置。配置示例:--base_step=1。 | 否 |
--comparison_step | 比对性能数据step ID,配置后使用比对性能数据对应step的数据进行比对。为整数,需配置实际数据存在的step ID,默认未配置,比对所有性能数据,需要与--base_step同时配置。配置示例:--comparison_step=1。 | 否 |
说明:以上开关均不设置的情况下,工具默认开启所有的性能比对,当用户设置了以上开关,则按照用户设置的开关进行性能比对,示例如下:
msprof-analyze compare -d [比对性能数据文件所在路径] -bp [基准性能数据文件所在路径] --output_path=./result_dir --enable_profiling_compare
或
python performance_compare.py [基准性能数据文件] [比对性能数据文件] --output_path=./result_dir --enable_profiling_compare
此时表示仅开启总体性能比对。
参数名 | 说明 | 是否必选 |
---|---|---|
--gpu_flow_cat | 配置GPU trace中CPU侧算子与device kernel的连线标识,当GPU的Device Duration(us)均为0时设置。使用chrome://tracing打开GPU的json,右上角Flow events找到连线标识,将标识配置进该参数。使用示例:--gpu_flow_cat=async_gpu | 否 |
--use_input_shape | 开启算子精准匹配,默认关闭。使用示例:--use_input_shape | 否 |
--max_kernel_num | 设置CPU侧算子下发的最大kernel数量,当超过设定值时工具会自动往下找子算子,直至满足条件。默认仅比对最上层算子,粒度较粗;若想要更细粒度的算子比对,可设置该参数,参数值不得小于4,参数值设置越小,比对粒度越细。使用示例:--max_kernel_num=10 | 否 |
--op_name_map | 设置GPU与NPU等价的算子名称的映射关系,以字典形式存入。使用示例:--op_name_map={'Optimizer.step#SGD.step':'Optimizer.step#NpuFusedSGD.step'} | 否 |
MindSpore场景仅支持总体性能和通信性能的对比。
比对结果分为打屏和performance_comparison_result_{timestamp}.csv两种形式输出,其中打屏输出为概要信息,csv文件保存详细结果。
总体性能比对结果以打屏的形式呈现时,字段如下:
字段 | 说明 |
---|---|
Cube Time(Num) | Cube算子总耗时,Num表示计算的次数。 |
Vector Time(Num) | Vector算子总耗时,Num表示计算的次数。 |
Conv Time(Forward)(Num) | conv前向算子耗时,Num表示计算的次数。 |
Conv Time(Backward)(Num) | conv反向算子耗时,Num表示计算的次数。 |
Flash Attention Time(Forward)(Num) | Flash Attention算子前向耗时,Num表示计算的次数。 |
Flash Attention Time(Backward)(Num) | Flash Attention算子反向耗时,Num表示计算的次数。 |
Paged Attention Time(Num) | Paged Attention算子耗时,Num表示计算的次数。 |
Lccl Time(Num) | Lccl算子耗时,Num表示计算的次数。 |
Computing Time | 计算流耗时,计算流所有event耗时总和。如果有多条并发计算,计算流耗时对重叠部分只会计算一次。 |
Mem Usage | 内存使用。GPU上的内存使用可以使用nvidia-smi查看,NPU上的内存使用可以使用npu-smi查看,Profiling信息采集时打开profile_memory=True开关,mem usage显示的是memory_record里面的最大resevered值,一般来说是进程级内存。 |
Uncovered Communication Time(Wait Time) | 通信未掩盖耗时。Wait Time为卡间等待时间(Wait Time仅NPU场景才会存在)。 |
RDMA Bandwidth(GB/s) | RDMA带宽,单位GB/s。 |
SDMA Bandwidth(GB/s) | SDMA带宽,单位GB/s。 |
SDMA Time(Num) | 拷贝类任务耗时,Num表示计算的次数。 |
Free Time | 调度耗时 = E2E耗时 - 算子耗时 - 通信不可掩盖耗时。Free的定义为Device侧既不在通信又不在计算的时间,因此包含拷贝时间(SDMA Time)。 |
E2E Time(Not minimal profiling) | E2E总耗时,计算流端到端耗时。当存在Not minimal profiling时,表示该时间存在性能膨胀,会影响通信和调度耗时。 |
Other Time | AI CPU、DSA、TensorMove等其他算子耗时。 |
总体性能比对结果在performance_comparison_result_*.xlsx中OverallMetrics的sheet页呈现时,示例如下:
表头字段说明:
字段 | 说明 |
---|---|
Index | 指标。 |
Duration(ms) | 执行耗时,单位ms。 |
Duration Ratio | 执行耗时占E2E总耗时的比例。 |
Number | 计算算子的数量。 |
Index列字段说明:
字段 | 说明 | ||
---|---|---|---|
Computing Time | 计算流耗时,计算流所有event耗时总和。如果有多条并发计算,计算流耗时对重叠部分只会计算一次。 NPU场景下,仅当采集性能数据的Level等级为L1及以上且aic_metrics取值为PipeUtilization时才可拆分出Computing Time的二级字段Flash Attention、Conv等。 |
||
Flash Attention | Flash Attention算子。 | ||
Flash Attention (Forward) (Cube) | Flash Attention前向算子下发的所有Cube类Kernel,一般为执行该算子核心计算的算子。 | ||
Flash Attention (Forward) (Vector) | Flash Attention前向算子下发的所有Vector类Kernel,一般为插入的转换类算子,如TransData。 | ||
Flash Attention (Backward) (Cube) | Flash Attention反向算子下发的所有Cube类Kernel,一般为执行该算子核心计算的算子。 | ||
Flash Attention (Backward) (Vector) | Flash Attention反向算子下发的所有Vector类Kernel,一般为插入的转换类算子,如TransData。 | ||
Conv | Conv算子。 | ||
Conv (Forward) (Cube) | Conv前向算子下发的所有Cube类Kernel,一般为执行该算子核心计算的算子。 | ||
Conv (Forward) (Vector) | Conv前向Vector算子。Conv前向算子下发的所有Vector类Kernel,一般为插入的转换类算子,如TransData。 | ||
Conv (Backward) (Cube) | Conv反向算子下发的所有Cube类Kernel,一般为执行该算子核心计算的算子。 | ||
Conv (Backward) (Vector) | Conv反向算子下发的所有Vector类Kernel,一般为插入的转换类算子,如TransData。 | ||
Matmul | Matmul算子。 | ||
Matmul (Cube) | Matmul算子下发的所有Cube类Kernel,一般为执行该算子核心计算的算子。 | ||
Matmul (Vector) | Matmul算子下发的所有Vector类Kernel,一般为插入的转换类算子,如TransData。 | ||
Paged Attention | Paged Attention算子。 | ||
Vector | Vector算子。 | ||
Vector (Trans) | 转换类Vector算子,主要包含Cast、TransPose、TransData算子。(仅针对NPU数据) | ||
Vector ( No Trans) | 非转换类Vector算子。 | ||
Cube | 未识别出Flash Attention、Conv和Matmul的Cube算子。 | ||
SDMA (Tensor Move) | 拷贝类任务。 | ||
Other | AI CPU、DSA等其他算子。 | ||
Uncovered Communication Time | 通信未掩盖耗时,包含卡间等待时间。 | ||
Wait | 卡间同步等待耗时。(仅针对NPU数据) | ||
Transmit | 通信传输耗时。 | ||
Free Time | 调度耗时 = E2E耗时 - 算子耗时 - 通信不可掩盖耗时。Free的定义为Device侧既不在通信又不在计算的时间,因此包含拷贝时间(SDMA Time)。 | ||
SDMA | NPU为除Tensor Move外的拷贝类任务,GPU为所有拷贝类任务。 | ||
Free | 排除SDMA的空闲耗时。 | ||
E2E Time | E2E总耗时,计算流端到端耗时。当存在Not minimal profiling时,表示该时间存在性能膨胀,会影响通信和调度耗时。 |
可以采取最简性能数据采集的方式来减少E2E耗时的性能膨胀,示例代码如下:
with torch_npu.profiler.profile(
activities=[torch_npu.profiler.ProfilerActivity.NPU],
schedule=torch_npu.profiler.schedule(wait=1, warmup=1, active=1, repeat=1, skip_first=10),
on_trace_ready=torch_npu.profiler.tensorboard_trace_handler("./result"),
) as prof:
for step in range(steps):
train_one_step()
prof.step()
activities配置仅采集NPU数据,不配置experimental_config参数以及其他可选开关。
MindSpore场景暂不支持。
算子性能比对结果在performance_comparison_result_{timestamp}.xlsx中OperatorCompare和OperatorCompareStatistic的sheet页呈现。
步骤1:查看OperatorCompareStatistic页,找出耗时差距TOP的算子。
步骤2:查看OperatorCompare页,搜索耗时差距TOP的算子,查看具体执行的kernel耗时,寻找可优化点。
算子性能比对结果在performance_comparison_result_*.xlsx中ModuleCompareStatistic、ModuleCompare的sheet页呈现。
当用户采集时开启with_stack开关,会上报python function事件,当比对的双方数据都存在python function的事件时,可进行模块级别的比对。
ModuleCompare:模块及模块下算子比对的明细展示,可以查看每一个算子对应的kernel详情。
步骤1:查看ModuleCompareStatistic页,找出耗时差距TOP的模块。
筛选Operator Name字段为[ TOTAL ],将模块总体情况按照Device Self Time(ms)字段逆序,可识别出耗时差距TOP的模块。
恢复数据,可按照Order Id字段升序。
步骤2:查看ModuleCompare页,查找耗时差距TOP模块下的劣化算子。
步骤3:通过调用栈找到对应的代码行。
通信性能比对结果在performance_comparison_result_*.xlsx中CommunicationCompare的sheet页呈现。
MindSpore场景暂不支持。
算子内存比对结果在performance_comparison_result_*.xlsx中MemoryCompare和MemoryCompareStatistic的sheet页呈现。
MemoryCompareStatistic:算子为粒度的统计呈现,按照算子占用的总内存与基准算子的差距值(Diff Memory(MB))进行逆序。
MemoryCompare:算子内存比对的明细展示,可以查看每一个算子申请内存的详情。
Diff Ratio: 比较算子占用的总内存 / 基准算子占用的总内存,红色代表劣化。
Size(KB):该算子占用的device内存大小,单位KB。
步骤1:查看MemoryCompareStatistic页,找出内存占用差距TOP的算子。 步骤2:查看MemoryCompare页,搜索内存占用差距TOP的算子,查看具体占用的子算子。
仅针对NPU与NPU比对的场景。
kernel比对结果在performance_comparison_result_*.xlsx中KernelCompare页呈现。
按照Kernel(Kernel类型)和Input Shapes(输入Shape)分组统计,统计信息包括:
API比对结果在performance_comparison_result_*.xlsx中ApiCompare页呈现。
按照api name(API名称)组统计,统计信息包括:
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。