背景概述

在深度学习模型的训练与推理过程中,性能分析(Profiling)是优化算力利用率、定位性能瓶颈的关键环节。torch_npu 是昇腾 NPU 上的 PyTorch 适配框架,其性能分析模块(Profiler)在 PyTorch Profiler 接口规范基础上进行扩展,提供算子执行、内存使用、通信操作等多维度的性能数据采集、解析与可视化能力。本文从模块架构、核心流程、状态机调度与工程实践等角度系统解析该模块的内部实现,为在昇腾 NPU 上进行性能调优的开发者提供参考。

1. 模块概述

torch_npu Profiler 模块是一款针对华为昇腾(Ascend)NPU 设备深度优化的性能分析工具。该模块在 PyTorch 原生 Profiler 功能基础上进行了扩展,为开发者提供涵盖 NPU 算子执行、内存使用、通信操作等多维度的全面性能分析能力。

1.1 主要功能

  • 算子性能采集:精确采集 CPU 端与 NPU 端算子的执行耗时,为性能瓶颈定位提供数据基础
  • 内存分析:全链路跟踪内存的分配、释放及使用情况,辅助识别内存泄漏与过度占用问题
  • Python 调用栈追踪:完整记录 Python 函数调用关系,帮助开发者理解代码执行路径
  • 通信分析:深入分析分布式训练场景下的通信操作效率,识别通信瓶颈
  • MSTX 标记:支持用户自定义性能标记点,实现细粒度的性能观测
  • TensorBoard 集成:生成兼容 TensorBoard 的可视化 trace 文件,提升数据分析效率
  • 多种导出格式:支持 JSON(Chrome Trace)、数据库(DB)等多种数据导出格式,满足不同分析场景需求

1.2 核心职责

组件职责
ProfilerMgr管理 Profiler 生命周期,控制数据采集开关
NpuProfilerThreadLocalState管理线程本地的 Profiler 状态
PythonTracer追踪 Python 函数调用
DataDumper将采集数据写入文件
ProfilingParser解析原始数据并生成可视化文件

2. 架构设计

2.1 Profiler 整体架构

+-----------------------------------------------------------------------------------+
|                              用户层 (User Layer)                                   |
|  +-------------+  +------------------+  +-------------------+  +---------------+  |
|  | profile()   |  | schedule()       |  | tensorboard_      |  | analyse()     |  |
|  | context     |  | ProfilerAction   |  | trace_handler()   |  |               |  |
|  +-------------+  +------------------+  +-------------------+  +---------------+  |
+-----------------------------------------------------------------------------------+
                                      |
                                      v
+-----------------------------------------------------------------------------------+
|                            Python 接口层 (Python Interface)                        |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | _KinetoProfile    |  | _ProfInterface     |  | _ExperimentalConfig       |     |
|  | profile           |  |                    |  |                           |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | ProfActionController| | ProfPathCreator   |  | ProfGCDetector           |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
+-----------------------------------------------------------------------------------+
                                      |
                                      v
+-----------------------------------------------------------------------------------+
|                         C++ 核心层 (C++ Core Layer)                                |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | ProfilerMgr       |  | NpuProfilerThread  |  | PythonTracer             |     |
|  | (单例模式)         |  | LocalState         |  |                          |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | MstxMgr           |  | FeatureMgr         |  | DataDumper               |     |
|  | (MSTX标记管理)     |  | (特性管理)          |  | (数据转储)                |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
+-----------------------------------------------------------------------------------+
                                      |
                                      v
+-----------------------------------------------------------------------------------+
|                          底层接口层 (Low-level Interface)                          |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | ACL Profiler API  |  | RecordFunction     |  | PyEval_SetProfile        |     |
|  | (aclprof*)        |  | Callback           |  | (Python C API)           |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
+-----------------------------------------------------------------------------------+
                                      |
                                      v
+-----------------------------------------------------------------------------------+
|                              数据解析层 (Data Parsing Layer)                       |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | ProfilingParser   |  | FwkFileParser      |  | CANNFileParser           |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | TreeBuilder       |  | TraceEventManager  |  | BinaryDecoder            |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
+-----------------------------------------------------------------------------------+
                                      |
                                      v
+-----------------------------------------------------------------------------------+
|                              可视化层 (Visualization Layer)                        |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | TraceViewParser   |  | OperatorViewParser |  | MemoryViewParser         |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  +-------------------+  +--------------------+  +---------------------------+     |
|  | KernelViewParser  |  | StackViewParser    |  | CommunicationParser      |     |
|  +-------------------+  +--------------------+  +---------------------------+     |
+-----------------------------------------------------------------------------------+

2.2 数据采集层设计

数据采集层负责在运行时收集各类性能数据,是整个 Profiler 系统的数据基础:

+-----------------------------------------------------------------------------------+
|                              数据采集层                                            |
+-----------------------------------------------------------------------------------+
|                                                                                   |
|  +------------------------+     +------------------------+                        |
|  |   CPU 数据采集         |     |   NPU 数据采集         |                        |
|  +------------------------+     +------------------------+                        |
|  |                        |     |                        |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  | | RecordFunction   |   |     | | ACL Profiler     |   |                        |
|  | | Callback         |   |     | | (aclprofStart)   |   |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  |         |              |     |         |              |                        |
|  |         v              |     |         v              |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  | | OpRangeData      |   |     | | NPU Trace Data   |   |                        |
|  | | (算子范围数据)    |   |     | | (NPU追踪数据)    |   |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  |                        |     |                        |                        |
|  +------------------------+     +------------------------+                        |
|                                                                                   |
|  +------------------------+     +------------------------+                        |
|  |   Python 追踪          |     |   内存数据采集         |                        |
|  +------------------------+     +------------------------+                        |
|  |                        |     |                        |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  | | PyEval_SetProfile|   |     | | MemoryAllocator  |   |                        |
|  | | PythonTracer     |   |     | | Hooks            |   |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  |         |              |     |         |              |                        |
|  |         v              |     |         v              |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  | | TraceEvent       |   |     | | MemoryData       |   |                        |
|  | | (追踪事件)        |   |     | | (内存数据)        |   |                        |
|  | +------------------+   |     | +------------------+   |                        |
|  |                        |     |                        |                        |
|  +------------------------+     +------------------------+                        |
|                                                                                   |
+-----------------------------------------------------------------------------------+
                      |
                      v
          +------------------------+
          |   RingBuffer           |
          |   (环形缓冲区)          |
          +------------------------+
                      |
                      v
          +------------------------+
          |   DataDumper           |
          |   (数据转储器)          |
          +------------------------+
                      |
                      v
          +------------------------+
          |   Binary Files         |
          |   (二进制文件)          |
          +------------------------+

2.3 数据解析层设计

数据解析层负责将采集到的原始二进制数据转换为结构化对象,为上层可视化提供统一的数据模型:

+-----------------------------------------------------------------------------------+
|                              数据解析层                                            |
+-----------------------------------------------------------------------------------+
|                                                                                   |
|   输入文件                                                                         |
|   +----------------+  +----------------+  +----------------+                      |
|   | torch.op_range |  | torch.op_mark  |  | torch.memory   |                      |
|   | (算子范围)      |  | (标记点)        |  | (内存使用)      |                      |
|   +----------------+  +----------------+  +----------------+                      |
|   +----------------+  +----------------+  +----------------+                      |
|   | python_tracer  |  | CANN profiler  |  | gc_record      |                      |
|   | _func/hash     |  | data           |  | (GC记录)        |                      |
|   +----------------+  +----------------+  +----------------+                      |
|           |                  |                  |                                 |
|           v                  v                  v                                 |
|   +------------------------------------------------------------------+           |
|   |                    BinaryDecoder / TLVDecoder                     |           |
|   |                    (二进制解码器)                                   |           |
|   +------------------------------------------------------------------+           |
|                                    |                                              |
|                                    v                                              |
|   +------------------------------------------------------------------+           |
|   |                         Bean 对象层                               |           |
|   | +---------------+ +---------------+ +---------------+             |           |
|   | | TorchOpBean   | | OpMarkBean    | | MemoryUseBean |             |           |
|   | +---------------+ +---------------+ +---------------+             |           |
|   | +---------------+ +---------------+ +---------------+             |           |
|   | | PythonTracer  | | GCRecordBean  | | NodeInfoBean  |             |           |
|   | | FuncBean      | |               | |               |             |           |
|   | +---------------+ +---------------+ +---------------+             |           |
|   +------------------------------------------------------------------+           |
|                                    |                                              |
|                                    v                                              |
|   +------------------------------------------------------------------+           |
|   |                         TreeBuilder                               |           |
|   |                    (构建算子调用树)                                 |           |
|   +------------------------------------------------------------------+           |
|                                                                                   |
+-----------------------------------------------------------------------------------+

2.4 可视化层设计

可视化层将解析后的数据转换为多种视图格式,支持不同维度的性能分析需求:

+-----------------------------------------------------------------------------------+
|                              可视化层                                              |
+-----------------------------------------------------------------------------------+
|                                                                                   |
|   +------------------------------------------------------------------+           |
|   |                    ParserConfig (解析器配置)                       |           |
|   |  - COMMON_CONFIG: 通用配置                                        |           |
|   |  - ONLY_FWK_CONFIG: 仅框架配置                                    |           |
|   |  - LEVEL_NONE_CONFIG: Level_none配置                             |           |
|   +------------------------------------------------------------------+           |
|                                    |                                              |
|                                    v                                              |
|   +------------------------------------------------------------------+           |
|   |              ConcurrentTasksManager (并发任务管理器)               |           |
|   +------------------------------------------------------------------+           |
|                                    |                                              |
|           +------------------------+------------------------+                     |
|           |                        |                        |                     |
|           v                        v                        v                     |
|   +----------------+       +----------------+       +----------------+            |
|   | TraceView      |       | OperatorView   |       | MemoryView     |            |
|   | Parser         |       | Parser         |       | Parser         |            |
|   | (时间线视图)    |       | (算子视图)      |       | (内存视图)      |            |
|   +----------------+       +----------------+       +----------------+            |
|           |                        |                        |                     |
|           v                        v                        v                     |
|   +----------------+       +----------------+       +----------------+            |
|   | trace_view.json|       | operator_*.csv |       | memory_*.csv   |            |
|   +----------------+       +----------------+       +----------------+            |
|                                                                                   |
|           +------------------------+------------------------+                     |
|           |                        |                        |                     |
|           v                        v                        v                     |
|   +----------------+       +----------------+       +----------------+            |
|   | KernelView     |       | StackView      |       | Communication  |            |
|   | Parser         |       | Parser         |       | Parser         |            |
|   | (Kernel视图)   |       | (调用栈视图)    |       | (通信视图)      |            |
|   +----------------+       +----------------+       +----------------+            |
|           |                        |                        |                     |
|           v                        v                        v                     |
|   +----------------+       +----------------+       +----------------+            |
|   | kernel_*.csv   |       | stack_*.txt    |       | comm_*.json    |            |
|   +----------------+       +----------------+       +----------------+            |
|                                                                                   |
+-----------------------------------------------------------------------------------+
                                    |
                                    v
+-----------------------------------------------------------------------------------+
|                           输出 (Output)                                            |
|   +----------------+       +----------------+       +----------------+            |
|   | Chrome Trace   |       | CSV Files      |       | SQLite DB      |            |
|   | JSON           |       |                |       |                |            |
|   +----------------+       +----------------+       +----------------+            |
|           |                        |                        |                     |
|           +------------------------+------------------------+                     |
|                                    |                                              |
|                                    v                                              |
|                          +----------------+                                       |
|                          | TensorBoard    |                                       |
|                          | 可视化          |                                       |
|                          +----------------+                                       |
+-----------------------------------------------------------------------------------+

3. 整体流程

3.1 Profiler 启动流程

Profiler 的启动遵循一套完整的初始化流程,确保各组件按序就绪:

用户调用 profile().__enter__()
            |
            v
+---------------------------+
| ProfPathCreator.init()    |
| 初始化输出路径             |
+---------------------------+
            |
            v
+---------------------------+
| _ProfInterface.init_trace()|
| 1. 创建 profiling 目录     |
| 2. 调用 _init_profiler()   |
+---------------------------+
            |
            v
+---------------------------+
| initNpuProfiler()         |
| (C++ 层)                   |
| 1. 验证路径有效性          |
| 2. ProfilerMgr::Init()    |
| 3. AclProfilingInit()     |
+---------------------------+
            |
            v
+---------------------------+
| 根据 schedule 决定动作     |
| - WARMUP: warmup_trace()  |
| - RECORD: start_trace()   |
+---------------------------+
            |
            v (如果是 start_trace)
+---------------------------+
| startNpuProfiler()        |
| (C++ 层)                   |
| 1. 创建 ThreadLocalState  |
| 2. ProfilerMgr::Start()   |
| 3. 注册 RecordFunction    |
|    Callback               |
| 4. 启动 PythonTracer      |
+---------------------------+
            |
            v
+---------------------------+
| ProfilerMgr::Start()      |
| 1. EnableMsProfiler()     |
| 2. StartDataReceiver()    |
| 3. 设置 report_enable_    |
+---------------------------+

3.2 数据采集流程

运行时数据采集是 Profiler 的核心工作环节,通过多通道并行采集确保数据的完整性和实时性:

+-----------------------------------------------------------------------------------+
|                              运行时数据采集                                         |
+-----------------------------------------------------------------------------------+

CPU 算子数据采集:
+---------------------------+
| PyTorch 执行算子          |
| 触发 RecordFunction       |
+---------------------------+
            |
            v
+---------------------------+
| 进入回调 (enter callback) |
| 1. 获取 ThreadLocalState  |
| 2. 创建 NpuObserverContext|
| 3. 记录开始时间戳         |
| 4. 解析输入形状/类型      |
| 5. 记录调用栈            |
+---------------------------+
            |
            v
+---------------------------+
| 退出回调 (exit callback)  |
| 1. 记录结束时间戳         |
| 2. ProfilerMgr::Upload()  |
+---------------------------+
            |
            v
+---------------------------+
| DataDumper::Report()      |
| 1. 数据入队 RingBuffer    |
| 2. 后台线程异步写文件     |
+---------------------------+

4. 核心数据采集流程

4.1 Python 追踪数据采集

Python 层追踪用于记录 Python 函数的调用关系与执行时间,其采集流程如下:


+---------------------------+
| Python 函数调用           |
| 触发 PyTrace_CALL         |
+---------------------------+
|
v
+---------------------------+
| PythonTracer::pyProfileFn |
| 1. 生成 hash id           |
| 2. 记录 TraceEvent        |
+---------------------------+
|
v
+---------------------------+
| 达到阈值时批量上报        |
| reportTraceData()         |
+---------------------------+

当 Python 函数被调用时,CPython 解释器触发 PyTrace_CALL 事件,PythonTracer::pyProfileFn 回调函数随即被调用。该函数为每个调用生成唯一的 hash id,并记录对应的 TraceEvent。当事件累积到一定阈值后,系统会批量上报数据,以降低频繁 I/O 带来的性能开销。

4.2 内存数据采集

内存数据采集关注 NPU 设备上的内存分配与释放行为,其流程如下:


+---------------------------+
| 内存分配/释放操作         |
| CachingAllocator 调用     |
+---------------------------+
|
v
+---------------------------+
| reportMemoryDataToNpuProfiler|
| 1. 创建 MemoryData        |
| 2. ProfilerMgr::          |
|    UploadWithLock()       |
+---------------------------+

当 CachingAllocator 执行内存分配或释放操作时,会触发 reportMemoryDataToNpuProfiler 回调。该回调构造 MemoryData 对象,并通过 ProfilerMgr::UploadWithLock() 方法将数据安全地提交至 Profiler 管理器,确保多线程环境下的数据一致性。


5. 数据导出流程

当用户调用 profile().__exit__() 或 step() 方法时,会触发 RECORD_AND_SAVE 动作,从而启动完整的数据导出流程:


用户调用 profile().__exit__() 或 step() 触发 RECORD_AND_SAVE
|
v
+---------------------------+
| ProfActionController.     |
| transit_action()          |
+---------------------------+
|
v
+---------------------------+
| _ProfInterface.stop_trace()|
| 1. _stop_profiler()       |
| 2. _disable_event_record()|
+---------------------------+
|
v
+---------------------------+
| stopNpuProfiler()         |
| (C++ 层)                   |
| 1. 移除 RecordFunction    |
|    Callback               |
| 2. 停止 PythonTracer      |
| 3. ProfilerMgr::Stop()    |
+---------------------------+
|
v
+---------------------------+
| ProfilerMgr::Stop()       |
| 1. npuSynchronizeDevice() |
| 2. StopDataReceiver()     |
| 3. AclProfilingStop()     |
| 4. 销毁 profConfig        |
+---------------------------+
|
v
+---------------------------+
| _ProfInterface.           |
| finalize_trace()          |
| 1. _finalize_profiler()   |
| 2. _dump_profiler_info()  |
| 3. _dump_metadata()       |
+---------------------------+
|
v
+---------------------------+
| on_trace_ready 回调       |
| tensorboard_trace_handler |
+---------------------------+
|
v
+---------------------------+
| NpuProfiler.analyse()     |
| 1. 获取 profiler 路径列表  |
| 2. 创建多进程池           |
| 3. 提交解析任务           |
+---------------------------+
|
v
+---------------------------+
| ProfilingParser.          |
| analyse_profiling_data()  |
| 1. 加载配置               |
| 2. 运行各类解析器         |
| 3. 数据简化处理           |
+---------------------------+

整个导出流程分为三个阶段:

  1. 停止采集阶段:通过 stopNpuProfiler() 移除回调、停止 Python Tracer,并调用 ProfilerMgr::Stop() 完成设备同步、停止数据接收器及 ACL Profiling 会话。
  2. 数据收尾阶段:finalize_trace() 负责将 Profiler 信息与元数据落盘。
  3. 数据解析阶段:通过 on_trace_ready 回调触发 NpuProfiler.analyse(),利用多进程池并行执行 ProfilingParser 中的各类解析器,最终生成可视化所需的中间文件。

6. 与 TensorBoard 集成流程

TensorBoard 集成是 Profiler 数据可视化的核心出口,其完整流程如下:


+---------------------------+
| tensorboard_trace_handler |
| 初始化输出路径            |
+---------------------------+
|
v
+---------------------------+
| profile 完成数据采集      |
| 触发 on_trace_ready       |
+---------------------------+
|
v
+---------------------------+
| handler_fn(prof_inst)     |
| 调用 prof_inst.analyse()  |
+---------------------------+
|
v
+---------------------------+
| NpuProfiler.analyse()     |
| analysis_type =           |
| TENSORBOARD_TRACE_HANDLER |
+---------------------------+
|
v
+---------------------------+
| ProfilingParser 执行      |
| ParserConfig.COMMON_CONFIG|
| 中的所有解析器            |
+---------------------------+
|
+---> TraceViewParser     --> trace_view.json
|
+---> OperatorViewParser  --> operator_details.csv
|
+---> KernelViewParser    --> kernel_details.csv
|
+---> MemoryViewParser    --> memory_record.csv
|
+---> CommunicationParser --> communication.json
|
v
+---------------------------+
| 输出到 ASCEND_PROFILER_   |
| OUTPUT 目录               |
+---------------------------+
|
v
+---------------------------+
| TensorBoard 加载          |
| trace_view.json           |
| tensorboard --logdir=xxx  |
+---------------------------+

当 tensorboard_trace_handler 被注册为 on_trace_ready 回调后,Profiler 会在数据采集完成后自动调用 NpuProfiler.analyse(),并指定分析类型为 TENSORBOARD_TRACE_HANDLER。随后,ProfilingParser 会依次执行 ParserConfig.COMMON_CONFIG 中注册的各类解析器,分别生成 trace 视图、算子详情、内核详情、内存记录及通信数据等文件,最终输出至指定目录供 TensorBoard 加载展示。


7. UML 类图设计

7.1 C++ 核心类图

C++ 核心层是 Profiler 的引擎,负责生命周期管理、数据采集与上报。核心类之间的关系如下:

ProfilerMgr

-static npu_metrics_map_ : map<string, aclprofAicoreMetrics>

-static trace_level_map_ : map<string, uint64_t>

-report_enable_ : atomic<bool>

-npu_trace_ : atomic<bool>

-profile_memory_ : atomic<bool>

-msprof_tx_ : atomic<bool>

-path_ : string

-profConfig_ : aclprofConfig

-dataReceiver_ : DataDumper

-traceDataReceiver_ : TraceDataDumper

+GetInstance() : ProfilerMgr

+Init(path, npu_trace)

+Warmup(npu_config, cpu_trace)

+Start(npu_config, cpu_trace)

+Stop()

+Finalize()

+Upload(data)

+UploadWithLock(data)

+UploadTraceEventData(data)

+UploadTraceHashData(data)

+ReportEnable() : atomic<bool>&

NpuProfilerThreadLocalState

#npu_config_ : NpuProfilerConfig

#activities_ : set<NpuActivityType>

#handle_ : CallbackHandle

+getTLS() : NpuProfilerThreadLocalState

+activities() : set<NpuActivityType>

+newOpEvent(fn) : unique_ptr<NpuObserverContext>

+memoryProfilingEnabled() : bool

+tracePython() : bool

NpuObserverContext

+data_ : unique_ptr<OpRangeData>

PythonTracer

-active_ : atomic<bool>

-interpreter_ : PyInterpreterState

-thread_local_results_ : deque<ThreadLocalResult>

-py_call_cache_ : unordered_map

-events_ : AppendOnlyList<TraceEvent>

+singleton() : PythonTracer&

+call(command)

+pyProfileFn(obj, frame, what, arg) : int

-start(max_threads)

-stop()

-clear()

-recordPyCall(ctx, frame)

-recordCCall(ctx, frame, arg)

-recordReturn(ctx, frame, tag)

MstxMgr

-ptRangeId_ : atomic<int>

-ptRangeIdsWithStream_ : unordered_set<int>

-mstxDomains_ : unordered_map<string, mstxDomainHandle_t>

+GetInstance() : MstxMgr

+mark(message, stream, domain)

+rangeStart(message, stream, domain) : int

+rangeEnd(ptRangeId, domain)

+isMstxEnable() : bool

+createProfDomain(name) : mstxDomainHandle_t

FeatureMgr

-profFeatures_ : unordered_map<FeatureType, FeatureInfo>

+GetInstance() : FeatureMgr

+Init()

+IsSupportFeature(featureName) : bool

DataDumper

-path_ : string

-start_ : atomic<bool>

-init_ : atomic<bool>

-data_chunk_buf_ : RingBuffer

+Init(path, capacity)

+UnInit()

+Report(data)

+Start()

+Stop()

-Flush()

-Dump(dataMap)

TraceDataDumper

-path_ : string

-trace_hash_data_ : unique_ptr<PythonTracerHashData>

-trace_data_buf_ : RingBuffer

+Init(path, capacity)

+Report(data)

+ReportHash(data)

+ReportParam(data)

BaseReportData

+device_id : int32_t

+tag : string

+encode() : vector<uint8_t>

OpRangeData

+start_ns : int64_t

+end_ns : int64_t

+sequence_number : int64_t

+process_id : uint64_t

+name : string

+input_dtypes : vector<string>

+input_shapes : vector<vector<int64_t>>

+stack : vector<string>

+encode() : vector<uint8_t>

MemoryData

+ptr : int64_t

+time_ns : int64_t

+alloc_size : int64_t

+total_allocated : int64_t

+total_reserved : int64_t

+device_type : int8_t

+device_index : int8_t

+encode() : vector<uint8_t>

关键设计说明:

  • ProfilerMgr 采用单例模式,是 Profiler 的全局控制中心,负责协调数据接收、状态管理及资源释放。
  • NpuProfilerThreadLocalState 保存线程本地的 Profiler 配置与回调句柄,确保多线程环境下的隔离性。
  • DataDumper 与 TraceDataDumper 分别负责通用性能数据与 Python 追踪数据的异步落盘。
  • BaseReportData 作为数据基类,OpRangeData 与 MemoryData 分别承载算子范围与内存事件信息。

7.2 Python 接口类图

Python 层封装了用户交互接口,负责将用户调用映射至 C++ 核心层:

profile

+activities : set<ProfilerActivity>

+schedule : Callable

+on_trace_ready : Callable

+record_steps : bool

+step_num : int

+action_controller : ProfActionController

+enter()

+exit(exc_type, exc_val, exc_tb)

+start()

+stop()

+step()

+enable_profiler_in_child_thread()

+disable_profiler_in_child_thread()

_KinetoProfile

+metadata : dict

+prof_if : _ProfInterface

+start()

+stop()

+export_chrome_trace(output_path)

+add_metadata(key, value)

+export_stacks(output_path, metric)

+export_memory_timeline(output_path, device)

_ProfInterface

+prof_path : string

+activities : set

+record_shapes : bool

+profile_memory : bool

+with_stack : bool

+experimental_config : _ExperimentalConfig

+init_trace()

+warmup_trace()

+start_trace()

+stop_trace()

+finalize_trace()

+analyse(analysis_type, output_path)

_ExperimentalConfig

-_profiler_level : int

-_aic_metrics : int

-_l2_cache : bool

-_msprof_tx : bool

-_data_simplification : bool

-_export_type : list

+export_type

+with_gc

+gc_detect_threshold

+call() : C_ExperimentalConfig

ProfActionController

+prof : profile

+prof_inst : _ProfInterface

+on_trace_ready : Callable

+action_map : dict

+transit_action(prev_action, current_action)

Schedule

+wait : int

+active : int

+warmup : int

+repeat : int

+skip_first : int

+call(step) : ProfilerAction

ProfilerAction

<>

NONE

WARMUP

RECORD

RECORD_AND_SAVE

ProfPathCreator

-_prof_path : string

-_worker_name : string

-_export_only_mode : bool

+init(worker_name, dir_name, export_only_mode)

+create_prof_dir()

+get_prof_dir() : string

+delete_prof_dir()

NpuProfiler

+analyse(input_path, analysis_type, output_path)

ProfilingParser

-_profiler_path : string

-_analysis_type : string

-_output_path : string

+analyse_profiling_data()

+run_parser() : list

+simplify_data(profiler_path, simplify_flag)

关键设计说明:

  • profile 类继承自 _KinetoProfile,是用户最常使用的入口,支持上下文管理器与显式 start/stop 两种模式。
  • Schedule 类实现了灵活的采集调度策略,支持 skip_first/wait/warmup/active/repeat 等参数组合。
  • ProfActionController 负责根据调度结果驱动 Profiler 状态机迁移。
  • NpuProfiler.analyse() 为静态方法,负责启动数据解析流程。

7.3 数据解析类图

数据解析层将原始 Profiling 数据转换为可视化文件,各类解析器协同工作:

BaseParser

#_profiler_path : string

#_output_path : string

#logger : ProfilerLogger

+run(deps_data) : tuple

TraceViewParser

-_trace_file_path : string

-_trace_data : list

-_torch_op_node : list

+run(deps_data) : tuple

+generate_view()

-_get_flow_event(msprof_timeline_data) : list

OperatorViewParser

+run(deps_data) : tuple

MemoryViewParser

+run(deps_data) : tuple

KernelViewParser

+run(deps_data) : tuple

StackViewParser

+run(deps_data) : tuple

CommunicationParser

+run(deps_data) : tuple

FwkFileParser

-_fwk_path : string

-_file_list : dict

+get_file_data_by_tag(file_tag) : list

+get_task_queue_data() : tuple

+get_torch_op_tree_node(torch_op_data, enqueue_data) : list

+get_fwk_trace_data(torch_op_data, enqueue_data_list, dequeue_data_list) : list

+get_python_trace_data(tid_dict) : list

CANNFileParser

-_cann_path : string

+get_timeline_all_data() : list

+combine_acl_to_npu(msprof_timeline_data) : dict

TreeBuilder

+build_tree(torch_op_data, enqueue_data) : list

+match_self_torch_op(acl_ts, root_node) : TorchOpNode

TraceEventManager

+create_x_event(op, category) : dict

+create_m_event(pid, tid_dict) : list

+create_torch_to_npu_flow(torch_event, kernel) : list

+create_fwd_flow(fwd_dict) : list

关键设计说明:

  • BaseParser 为所有解析器提供统一的接口与公共属性。
  • TraceViewParser 是核心解析器,依赖 FwkFileParser 与 CANNFileParser 分别读取框架侧与 CANN 侧数据,并通过 TreeBuilder 构建算子树、TraceEventManager 生成 Trace 事件。
  • 各视图解析器(Operator/Kernel/Memory/Stack/Communication)独立运行,输出对应的 CSV 或 JSON 文件。

8. 关键代码实现细节

8.1 ProfilerActivity 的实现

ProfilerActivity 枚举定义了 Profiler 可采集的活动类型,涵盖 CPU 端与 NPU 端算子追踪。

C++ 定义(npu_profiler.h):

enum class NpuActivityType {
    NONE = 0,
    CPU,   // CPU 端算子追踪
    NPU,   // NPU 端算子追踪
};

Python 绑定(init.cpp):

py::enum_(m, "ProfilerActivity")
    .value("CPU", NpuActivityType::CPU)
    .value("NPU", NpuActivityType::NPU);

活动查询接口(profiler_interface.py):

@no_exception_func(set())
def supported_activities():
    return _supported_npu_activities()

8.2 NPU 钩子的实现

NPU Profiler 通过 RecordFunction 回调机制捕获 CPU 端算子执行事件。

回调注册(npu_profiler.cpp):

static void registerCallback(const std::unordered_set &scopes)
{
    auto registeration_state_ptr = NpuProfilerThreadLocalState::getTLS();
    TORCH_INTERNAL_ASSERT(registeration_state_ptr, "Expected profiler state set");

    auto handle = at::addThreadLocalCallback(
        at::RecordFunctionCallback(
            // 进入回调 - 记录算子开始
            [](const at::RecordFunction &fn) -> std::unique_ptr {
                auto state_ptr = NpuProfilerThreadLocalState::getTLS();
                if (!state_ptr) {
                    return nullptr;
                }
                const auto &config = state_ptr->config();
                auto ctx_ptr = state_ptr->newOpEvent(fn);
                auto &data_ptr = ctx_ptr->data_;

                // 记录输入形状和类型
                if ((C10_UNLIKELY(config.report_input_shapes))) {
                    parseInputShapesAndDtypes(fn, data_ptr.get(), report_details);
                }
                // 记录调用栈
                if (C10_UNLIKELY(config.with_stack && fn.scope() != at::RecordScope::BACKWARD_FUNCTION)) {
                    auto cs = torch::profiler::impl::prepareCallstack(torch::jit::currentCallstack());
                    data_ptr->stack = torch::profiler::impl::callstackStr(cs);
                }
                return ctx_ptr;
            },
            // 退出回调 - 记录算子结束
            [](const at::RecordFunction &fn, at::ObserverContext *ctx_ptr) {
                auto state_ptr = NpuProfilerThreadLocalState::getTLS();
                if (!state_ptr) {
                    return;
                }
                auto *npu_ctx_ptr = static_cast(ctx_ptr);
                auto data_ptr = std::move(npu_ctx_ptr->data_);
                data_ptr->end_ns = static_cast(Utils::GetClockTime());
                data_ptr->end_thread_id = Utils::GetTid();

                // 上报数据
                if (ProfilerMgr::GetInstance()->ReportEnable().load(std::memory_order_relaxed)) {
                    ProfilerMgr::GetInstance()->Upload(std::move(data_ptr));
                }
            }
        )
        .needsInputs(registeration_state_ptr->config().report_input_shapes)
        .scopes(scopes)
    );
    registeration_state_ptr->setCallbackHandle(handle);
}

8.3 日志记录机制

Profiler 采用异步数据转储机制,最小化对训练性能的影响。

DataDumper 类(data_dumper.h):

class DataDumper : public Thread {
public:
    void Init(const std::string &path, size_t capacity);
    void Report(std::unique_ptr data);
    void Start();
    void Stop();

private:
    std::string path_;
    std::atomic start_;
    std::atomic init_;
    RingBuffer> data_chunk_buf_;  // 环形缓冲区
    std::map fd_map_;
};

数据上报流程(profiler_mgr.cpp):

void ProfilerMgr::Upload(std::unique_ptr data)
{
    if (enable_warmup_.load()) {
        return;  // warmup 期间不记录数据
    }
    dataReceiver_.Report(std::move(data));
}

void ProfilerMgr::UploadWithLock(std::unique_ptr data)
{
    if (enable_warmup_.load()) {
        return;
    }
    std::lock_guard lock(reportDataMutex_);
    dataReceiverWithLock_.Report(std::move(data));
}

8.4 Python Tracer 实现

Python Tracer 利用 CPython 的 Profile 机制追踪 Python 函数调用。

核心实现(profiler_python.cpp):

class PythonTracer final {
public:
    static int pyProfileFn(
        PyObject* obj,
        PyFrameObject* frame,
        int what,
        PyObject* arg);

private:
    void start(size_t max_threads = max_py_threads);
    void stop();
    void recordPyCall(TraceContext* ctx, PyFrameObject* frame);
    void recordCCall(TraceContext* ctx, PyFrameObject* frame, PyObject* arg);
    void recordReturn(TraceContext* ctx, PyFrameObject* frame, TraceTag tag);

    std::atomic active_{false};
    PyInterpreterState* interpreter_{nullptr};
    std::unordered_map py_call_cache_;
    AppendOnlyList events_;
};

// Profile 回调函数
int PythonTracer::pyProfileFn(
    PyObject* obj,
    PyFrameObject* frame,
    int what,
    PyObject* arg)
{
    auto ctx = reinterpret_cast(obj);
    auto active_tracer = ctx->thread_local_result_->active_tracer_;

    switch (what) {
        case PyTrace_CALL:
            active_tracer->recordPyCall(ctx, frame);
            break;
        case PyTrace_C_CALL:
            active_tracer->recordCCall(ctx, frame, arg);
            break;
        case PyTrace_RETURN:
            active_tracer->recordReturn(ctx, frame, TraceTag::kPy_Return);
            break;
        case PyTrace_C_RETURN:
            active_tracer->recordReturn(ctx, frame, TraceTag::kC_Return);
            break;
    }
    return 0;
}

8.5 调度器实现

调度器控制 Profiler 的采集周期,支持灵活的采样策略。

文件路径:scheduler.py

class ProfilerAction(Enum):
    NONE = 0           # 不采集
    WARMUP = 1         # 预热阶段
    RECORD = 2         # 正常记录
    RECORD_AND_SAVE = 3  # 记录并保存

class Schedule:
    """
    调度器控制 Profiler 的采集周期:
    skip_first -> wait -> warmup -> active (repeat)
    """
    def __init__(self, wait: int, active: int, warmup: int = 0,
                 repeat: int = 0, skip_first: int = 0):
        self.wait = wait
        self.active = active
        self.warmup = warmup
        self.repeat = repeat
        self.skip_first = skip_first

    def __call__(self, step: int) -> ProfilerAction:
        if step < self.skip_first:
            return ProfilerAction.NONE
        step -= self.skip_first
        num_steps = self.wait + self.warmup + self.active
        if self.repeat > 0 and step / num_steps >= self.repeat:
            return ProfilerAction.NONE
        mod_step = step % num_steps
        if mod_step < self.wait:
            return ProfilerAction.NONE
        elif mod_step < self.wait + self.warmup:
            return ProfilerAction.WARMUP
        else:
            return (ProfilerAction.RECORD
                    if mod_step < num_steps - 1
                    else ProfilerAction.RECORD_AND_SAVE)

8.6 状态转换控制器

状态转换控制器负责根据调度结果驱动 Profiler 状态机迁移。

文件路径:_profiler_action_controller.py

class ProfActionController:
    def __init__(self, prof, prof_inst, on_trace_ready):
        self.prof = prof
        self.prof_inst = prof_inst
        self.action_map = self._init_action_map()
        self.on_trace_ready = on_trace_ready

9. 状态机调度与工程实践

9.1 状态机调度机制

在 Profiler 的调度系统中,状态机是核心的调度控制机制。通过定义明确的动作状态和转换规则,状态机能够精确控制 Profiler 在不同阶段的启停行为,确保数据采集的准确性和完整性。

9.1.1 状态定义

Profiler 的调度状态机定义了以下核心状态:

状态说明
NONE空闲状态,Profiler 未执行任何采集动作
WARMUP预热阶段,执行初始化但不记录数据
RECORD正式采集阶段,记录性能数据
RECORD_AND_SAVE采集并保存数据阶段
9.1.2 状态转换实现

状态转换通过动作映射表驱动,每个状态对对应一组待执行的动作:

def transit_action(self, prev_action, current_action):
    action_list = self.action_map.get((prev_action, current_action))
    if action_list:
        for action in action_list:
            action()

def _init_action_map(self):
    return {
        # NONE -> WARMUP: 初始化并预热
        (ProfilerAction.NONE, ProfilerAction.WARMUP): [
            self.prof_inst.init_trace,
            self.prof_inst.warmup_trace
        ],
        # WARMUP -> RECORD: 开始正式记录
        (ProfilerAction.WARMUP, ProfilerAction.RECORD): [
            self.prof_inst.start_trace
        ],
        # RECORD_AND_SAVE -> NONE: 停止并保存
        (ProfilerAction.RECORD_AND_SAVE, ProfilerAction.NONE): [
            self.prof_inst.stop_trace,
            self.prof_inst.finalize_trace,
            self._trace_ready
        ],
        # ... 其他状态转换
    }

9.2 关键文件路径汇总

功能模块文件路径
C++ 核心实现—
Profiler 主入口torch_npu/csrc/profiler/npu_profiler.cpp
Profiler 头文件torch_npu/csrc/profiler/npu_profiler.h
Profiler 管理器torch_npu/csrc/profiler/profiler_mgr.cpp
Python Tracertorch_npu/csrc/profiler/profiler_python.cpp
MSTX 管理器torch_npu/csrc/profiler/mstx_mgr.cpp
特性管理器torch_npu/csrc/profiler/feature_mgr.cpp
Python 绑定torch_npu/csrc/profiler/init.cpp
数据转储器torch_npu/csrc/toolkit/profiler/inc/data_dumper.h
数据上报结构torch_npu/csrc/toolkit/profiler/inc/data_reporter.h
Python 接口—
模块入口torch_npu/profiler/__init__.py
Profile 类torch_npu/profiler/profiler.py
调度器torch_npu/profiler/scheduler.py
实验配置torch_npu/profiler/experimental_config.py
Profiler 接口torch_npu/profiler/profiler_interface.py
动作控制器torch_npu/profiler/_profiler_action_controller.py
路径创建器torch_npu/profiler/_profiler_path_creator.py
数据解析—
解析入口torch_npu/profiler/analysis/_npu_profiler.py
解析器主类torch_npu/profiler/analysis/_profiling_parser.py
框架文件解析torch_npu/profiler/analysis/prof_parse/_fwk_file_parser.py
Trace 视图解析torch_npu/profiler/analysis/prof_view/_trace_view_parser.py
常量定义torch_npu/profiler/analysis/prof_common_func/_constant.py

9.3 特性与优化方向

9.3.1 核心优势
优势说明
完整的 PyTorch 兼容性采用与 PyTorch Profiler 相同的 API 设计,用户学习成本低
多级别追踪支持支持 Level0/Level1/Level2 等不同精度的追踪,用户可按需选择
异步数据采集使用 RingBuffer + 后台线程异步写入,最小化对训练性能的影响
灵活的调度机制支持 skip_first/wait/warmup/active/repeat 等多种调度参数
完善的 Python 追踪支持 Python 函数调用栈追踪,便于定位性能瓶颈
TensorBoard 集成原生支持 TensorBoard 可视化,便于分析
多进程解析支持多进程并行解析,提高大规模数据解析效率
丰富的视图输出支持 Trace View、Operator View、Memory View 等多种视图
GC 检测支持 Python GC 事件检测,帮助分析内存问题
MSTX 标记支持用户自定义标记点和区间,便于精细化分析
9.3.2 后续演进方向

性能优化

  • 采样机制:引入采样率参数,允许用户只记录部分算子;实现基于时间窗口的采样策略
  • 增量式数据转储:支持边采集边写入的流式转储,进一步降低数据落盘对内存的占用
  • 压缩存储:对重复的字符串(如算子名、调用栈)进行去重存储;支持 gzip 压缩输出

功能增强

  • 实时监控:提供实时 profiling 数据流接口;支持 Prometheus/Grafana 集成
  • 智能分析:自动识别性能瓶颈;提供优化建议
  • 分布式支持增强:自动聚合多 rank 数据;支持集群级别的性能分析
  • 更细粒度的控制:支持按算子名过滤;支持按模块过滤

易用性改进

  • 错误处理与提示:进一步完善参数校验与错误提示,提升使用友好性
  • 文档完善:提供更多使用示例;增加 FAQ 文档
  • CLI 工具:提供命令行分析工具;支持离线数据查看

代码质量

  • 单测与集成:持续完善 C++ 层单元测试与集成测试,保障模块长期质量
  • 代码重构:持续统一错误码定义、精简重复代码,提升可维护性

9.4 Python API 使用指南

9.4.1 基础用法
import torch
import torch_npu
from torch_npu.profiler import profile, ProfilerActivity

# 基础用法 - 使用 context manager
model = MyModel().npu()
inputs = torch.randn(32, 3, 224, 224).npu()

with profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.NPU],
    record_shapes=True,
    profile_memory=True,
    with_stack=True,
) as prof:
    for _ in range(10):
        output = model(inputs)

# 导出 Chrome Trace 格式
prof.export_chrome_trace("trace.json")
9.4.2 使用调度器控制采集周期
import torch
import torch_npu
from torch_npu.profiler import (
    profile,
    ProfilerActivity,
    schedule,
    tensorboard_trace_handler
)

model = MyModel().npu()
inputs = torch.randn(32, 3, 224, 224).npu()

# 使用调度器: 跳过前5步,等待1步,预热1步,采集3步,重复2次
with profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.NPU],
    schedule=schedule(
        skip_first=5,
        wait=1,
        warmup=1,
        active=3,
        repeat=2
    ),
    on_trace_ready=tensorboard_trace_handler(
        dir_name="./profiler_logs",
        worker_name="worker0"
    ),
    record_shapes=True,
    profile_memory=True,
) as prof:
    for step in range(20):
        output = model(inputs)
        prof.step()  # 必须调用 step() 来触发调度
9.4.3 使用实验配置
import torch
import torch_npu
from torch_npu.profiler import (
    profile,
    ProfilerActivity,
    _ExperimentalConfig,
    ProfilerLevel,
    AiCMetrics,
    ExportType
)

# 配置高级选项
experimental_config = _ExperimentalConfig(
    profiler_level=ProfilerLevel.Level1,  # 使用 Level1 追踪级别
    aic_metrics=AiCMetrics.PipeUtilization,  # AI Core 流水线利用率
    l2_cache=True,  # 开启 L2 缓存统计
    mstx=True,  # 开启 MSTX 标记
    data_simplification=True,  # 数据简化
    export_type=[ExportType.Text, ExportType.Db],  # 同时导出文本和数据库
    gc_detect_threshold=0.1,  # GC 检测阈值(秒)
)

with profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.NPU],
    experimental_config=experimental_config,
    record_shapes=True,
    profile_memory=True,
    with_stack=True,
    with_modules=True,
) as prof:
    for _ in range(10):
        output = model(inputs)
9.4.4 子线程 Profiling
import threading
import torch
import torch_npu
from torch_npu.profiler import profile, ProfilerActivity

def worker_thread():
    # 在子线程中启用 profiler
    profile.enable_profiler_in_child_thread(
        record_shapes=True,
        profile_memory=True,
        with_stack=True
    )

    try:
        # 执行计算
        x = torch.randn(100, 100).npu()
        y = torch.matmul(x, x)
    finally:
        # 禁用 profiler
        profile.disable_profiler_in_child_thread()

# 主线程开启 profiler
with profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.NPU],
) as prof:
    # 创建并启动子线程
    thread = threading.Thread(target=worker_thread)
    thread.start()
    thread.join()
9.4.5 使用 MSTX 标记
import torch
import torch_npu
from torch_npu.profiler import profile, ProfilerActivity, _ExperimentalConfig

# MSTX 标记需要开启 mstx 选项
experimental_config = _ExperimentalConfig(mstx=True)

with profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.NPU],
    experimental_config=experimental_config,
) as prof:
    # 使用 record_function 添加标记
    with torch.profiler.record_function("my_custom_region"):
        x = torch.randn(1000, 1000).npu()
        y = torch.matmul(x, x)

    # 另一个标记
    with torch.profiler.record_function("another_region"):
        z = torch.relu(y)
9.4.6 导出内存时间线
import torch
import torch_npu
from torch_npu.profiler import profile, ProfilerActivity

with profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.NPU],
    record_shapes=True,
    profile_memory=True,
    with_stack=True,  # 内存分析需要调用栈
) as prof:
    for _ in range(10):
        x = torch.randn(1000, 1000).npu()
        y = torch.matmul(x, x)
        del x, y
        torch_npu.npu.empty_cache()

# 导出内存时间线
prof.export_memory_timeline("memory_timeline.html", device="npu:0")
9.4.7 离线数据分析
from torch_npu.profiler import analyse

# 离线分析已采集的 profiling 数据
analyse(
    profiler_path="./profiler_logs/worker0_20240101120000_ascend_pt",
    max_process_number=8,  # 使用 8 个进程并行解析
    export_type=["text", "db"]  # 导出文本和数据库格式
)
9.4.8 完整训练循环示例
import torch
import torch.nn as nn
import torch.optim as optim
import torch_npu
from torch_npu.profiler import (
    profile,
    ProfilerActivity,
    schedule,
    tensorboard_trace_handler,
    _ExperimentalConfig,
    ProfilerLevel
)

# 模型定义
class SimpleModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 256)
        self.fc2 = nn.Linear(256, 10)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        return self.fc2(x)

# 初始化
device = torch.device("npu:0")
model = SimpleModel().to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

# 配置 Profiler
experimental_config = _ExperimentalConfig(
    profiler_level=ProfilerLevel.Level1,
    data_simplification=True,
)

# 训练循环
with profile(
    activities=[ProfilerActivity.CPU, ProfilerActivity.NPU],
    schedule=schedule(skip_first=10, wait=5, warmup=1, active=3, repeat=2),
    on_trace_ready=tensorboard_trace_handler("./tb_logs"),
    record_shapes=True,
    profile_memory=True,
    with_stack=True,
    experimental_config=experimental_config,
) as prof:
    for epoch in range(3):
        for batch_idx in range(100):
            # 模拟数据
            data = torch.randn(32, 784).to(device)
            target = torch.randint(0, 10, (32,)).to(device)

            # 前向传播
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)

            # 反向传播
            loss.backward()
            optimizer.step()

            # 重要: 调用 step() 触发调度器
            prof.step()

print("Profiling 完成! 使用 TensorBoard 查看结果:")
print("tensorboard --logdir=./tb_logs")

10. 总结

本文系统解析了 torch_npu 性能分析模块(Profiler)的内部实现,涵盖模块架构与整体流程、核心数据采集与导出链路、TensorBoard 集成方案、关键类图设计与代码实现,以及状态机调度机制与工程实践。通过分层架构、环形缓冲与异步写入、多进程解析等机制,该模块在保证性能数据完整性的同时,尽可能降低了对训练任务的干扰,并为开发者提供从基础用法、调度控制、实验配置到离线分析的一整套使用路径。开发者可结合本文的分析思路与 API 示例,针对具体业务场景在昇腾 NPU 上开展性能分析与优化。

附录 A: 数据文件格式

A.1 二进制文件结构

torch.op_range 文件采用 TLV (Type-Length-Value) 编码:

+------------------+------------------+------------------+
|  Type (2 bytes)  | Length (4 bytes) | Value (N bytes)  |
+------------------+------------------+------------------+

A.2 输出目录结构

profiler_output/
├── FRAMEWORK/                    # 框架层数据
│   ├── torch.op_range           # 算子范围数据
│   ├── torch.op_mark            # 标记点数据
│   ├── torch.memory_usage       # 内存使用数据
│   ├── torch.python_tracer_func # Python 函数追踪
│   └── torch.python_tracer_hash # Python 函数哈希表
├── PROF_*/                       # CANN 层数据
│   └── ...
├── ASCEND_PROFILER_OUTPUT/       # 解析输出
│   ├── trace_view.json          # Chrome Trace 格式
│   ├── operator_details.csv     # 算子详情
│   ├── kernel_details.csv       # Kernel 详情
│   ├── memory_record.csv        # 内存记录
│   └── ...
├── profiler_info.json           # Profiler 配置信息
└── profiler_metadata.json       # 元数据

附录 B: 常见问题与解决方案

Q1: 如何控制 Profiling 采集带来的额外开销?

A:性能分析工具在采集数据时会产生一定的额外开销,这是 Profiling 机制的通用特性,可通过以下方式将其控制在合理范围:

  1. 减少 profiling 范围,使用 schedule 限制采集步数
  2. 按需关闭 with_stack 和 Python Tracer
  3. 按需选择较低的追踪级别(如 Level0)

Q2: 无法生成 trace_view.json?

A:

  1. 检查输出目录是否可写
  2. 确认 profiling 正常结束(调用了 stop)
  3. 查看是否在 daemon 进程中

Q3: 子线程数据没有被采集?

A:
需要在子线程中显式调用:

profile.enable_profiler_in_child_thread()
# ... 执行代码 ...
profile.disable_profiler_in_child_thread()
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐