使用MindStudio Insight加载Linux Kernel数据以联合分析Host Bound问题
问题背景
在大模型中,CPU主要负责任务的下发,NPU负责计算任务的执行。无论训练还是推理领域,Host Bound都是现网高发问题。分析Host Bound问题通常需要采集Linux Kernel ftrace数据,分析CPU上的进程调度情况。
目前缺乏一种工具,能够统合profiling数据和Linux Kernel ftrace数据,做到联合分析。MindStudio Insight在本仓库中,提出一些工具脚本,帮助开发者实现两种数据的联合分析,提高Host Bound问题定位的效率。
特性
- 支持命令行和API接口两种方式的ftrace数据采集
- 支持将ftrace格式数据转换为SQLite DB格式(默认)或Chrome Trace JSON格式,联合Profiling数据导入MindStudio Insight,进行可视化展示
- 支持容器内运行模型,宿主机采集Linux Kernel ftrace数据,并进行无缝PID映射
Host Bound问题定位思路
- 尝试通用的调度优化手段,包括绑核、流水优化、内存分配库替换三板斧。PyTorch框架调度优化可参考:调度优化-Ascend Extension for PyTorch-昇腾社区
- 若通用优化手段效果不及预期,可采集数据,进一步深入分析。建议同时采集ftrace和profiling数据。
- 将ftrace数据转换为MindStudio Insight可识别的数据格式。
- 同时导入ftrace数据与profiling数据,分析进程调度情况。
模型Profiling采集
参考昇腾社区有关profiling采集相关的文档:简介-CANN商用版8.3.RC1-昇腾社区
请注意Profiling采集配置。当前仅支持ftrace与Text类型的Profiling联合导入,暂不支持与DB类型的Profiling数据联合导入。
Linux Kernel ftrace数据采集
1. Linux Kernel ftrace数据简介
Linux内核内置了多种跟踪(trace)工具,其中ftrace作为从2.6.27版本开始引入主流内核的跟踪框架,可用于监控和调试内核中发生的各类事件,帮助开发人员深入分析系统运行时的内部行为。ftrace支持多种跟踪器,例如函数调用跟踪、上下文切换跟踪、中断延迟分析等,能够有效辅助定位内核态性能问题与调度异常。 在本仓库中,提供了与CPU进程调度相关的事件(sched)、中断 / 软中断相关事件(irq)的采集能力。
trace-cmd是一个命令行工具,它封装了trace采集的过程,提供了更加简易的命令接口。
2. 数据采集前置准备
-
安装trace-cmd命令
Ubuntu安装命令:
sudo apt-get install trace-cmdCentOs安装命令:
sudo yum install trace-cmd -
获取仓库中提供的采集、转换脚本
trace_record.py,trace_convert.py,推荐profiling和ftrace数据同步采集。
若目标环境不支持安装trace-cmd,可使用脚本内置的tracefs/debugfs采集模式。该模式直接通过内核 tracing 文件系统配置 ftrace,并输出文本格式 trace 文件,使用差异详见下文tracefs/debugfs模式支持。
3. ftrace数据采集
支持命令行和API接口两种方式的ftrace数据采集。
方式一:命令行采集
这种方式不需要修改现有代码,将trace_record.py脚本作为整体使用,易上手,但自定义程度相对有限。
参数说明
| 参数 | 说明 | 示例 | 默认值 |
|---|---|---|---|
--cpu |
cpu_mask 列表,指定采集的 CPU 核心。支持单个数字、逗号分隔及连字符范围。 | --cpu=0,1,4 (指定核)--cpu=0-3,8 (混合写法)--cpu=0-15 (范围写法) |
None,采集 全部 CPU 核心 |
--output |
输出文件路径与文件名。 | --output=my_trace_data.dat |
trace.dat |
--record_time |
采集持续时间(单位:秒)。 • 正值:采集指定秒数后自动停止; • ≤0:持续采集,需 Ctrl+C 手动终止,长时间采集请注意磁盘空间占用。 |
--record_time=30 |
30 |
--bf_size |
脚本使用的 ring buffer 大小(单位:KB),用于在内核侧缓存 ftrace 事件。 当采集数据量较大时,可适当增大该值,避免环形缓冲区数据覆盖导致 trace event 丢失;若发生覆盖,采集结束打印回显会告警,tracefs/debugfs模式推荐配置为大于40960KB。 |
--bf_size=40960 |
40960 |
--backend |
ftrace采集后端。 • auto默认模式,表示优先使用trace-cmd,trace-cmd不可用时自动回退到tracefs/debugfs;• trace-cmd表示强制使用trace-cmd;• debugfs表示强制使用tracefs/debugfs模式 |
--backend=debugfs |
auto |
--sched |
是否采集 CPU 调度相关事件,包括任务切换、唤醒、新任务启动等(如 sched_switch、sched_wakeup、sched_wakeup_new)。主要用于分析 调度延迟、任务切换频率、线程唤醒关系。 • 1:开启• 0:关闭 |
--sched=1--sched=0 |
1(开启) |
--irq |
是否采集 中断 / 软中断相关事件,包括硬中断与 softirq 的进入、退出及触发行为。 主要用于分析 中断负载、软中断抖动、CPU 被中断打断的情况。 • 1:开启• 0:关闭 |
--irq=1--irq=0 |
1(开启) |
--NSpid |
容器场景下开启该开关,用于获取容器与宿主机 PID 映射关系,详见容器内外PID命名空间隔离场景下采集。 | --NSpid |
关闭 |
使用示例:
场景:采集CPU核心0-4的30秒训练数据
1. 启动数据采集(需root权限):
sudo python trace_record.py --record_time=30 --cpu=0,1,2,3,4
注意:此处的--cpu=0,1,2,3,4仅为示例,实际使用时,建议根据绑核策略,选取一定量的CPU核心进行采集(推荐CPU采集核心数不超过64,采集时长30s左右,否则采集数据量可能过大,解析落盘耗时较长,需耐心等待)。
2. 执行训练任务(在新终端中):
python train.py
3. 采集结果:
脚本运行30秒后自动停止,默认生成 trace.dat 文件(或通过 --output 参数指定文件名)。
tracefs/debugfs模式说明: 当使用
--backend=debugfs(或使用默认--backend=auto且环境中没有trace-cmd时),脚本输出会自动调整为文本格式trace文件,默认生成trace.txt文件(或通过 --output 参数指定文件名)。
方式二:API接口采集模式
trace_record.py中提供两个接口,分别控制ftrace采集的启停,允许开发者将数据采集逻辑精细地嵌入到应用程序中。这种方式适合需要动态控制采集时机、条件触发采集或与业务逻辑深度集成的场景。
1. 开始采集接口
ftrace_record_start(cpu_mask=None, output="trace.dat", bf_size=DEFAULT_TRACE_BUFFER_SIZE, event_cfg: TraceEventConfig = None, args=None, backend="auto")
参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
cpu_mask |
cpu_mask 列表,指定采集的 CPU 核心。支持 List[int] 或字符串(如 "0-3,8") |
None,采集 全部 CPU 核心 |
bf_size |
脚本使用的 ring buffer 大小(单位:KB),用于在内核侧缓存 ftrace 事件。 当采集数据量较大时,可适当增大该值,避免环形缓冲区数据覆盖导致 trace event 丢失 |
--bf_size=40960 |
backend |
ftrace采集后端,可选auto、trace-cmd、debugfs。其中debugfs表示使用tracefs/debugfs模式。 |
auto |
output |
输出文件路径与文件名。 | trace.dat |
event_cfg |
事件采集配置(TraceEventConfig),用于控制采集事件类型:sched(调度)、irq(中断)。1表示打开,0表示关闭。 |
TraceEventConfig(sched=1, irq=1) |
注意:推荐CPU采集核心数不超过64,采集时长30s左右,否则采集数据量可能过大,解析落盘耗时较长,需耐心等待。
2. 停止采集并保存数据接口
def ftrace_record_stop(output=None)
参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
output |
输出文件的路径和名称 | trace.dat |
使用示例:
import trace_record
def train():
# 方式一:传入字符串范围(可混合)
trace_record.ftrace_record_start(cpu_mask="0-4,7,10")
# 方式二:传入列表
trace_record.ftrace_record_start(cpu_mask=[0,1,2,3,4])
profiling_start()
# 模型运行...
profiling_stop()
trace_record.ftrace_record_stop(output="trace.dat")
4. 数据采集后处理
trace_convert.py脚本用于将原始 ftrace 数据转换为 SQLite DB 格式(默认)或 Chrome Trace JSON 格式,并与所采集的profiling数据时间轴对齐,以便导入 MindStudio Insight 可视化工具联合展示与分析。
请注意Profiling采集配置。当前仅支持ftrace与Text类型的Profiling联合展示,暂不支持与DB类型的Profiling数据联合展示。当ftrace导出为db格式时,如果需要与Text类型的Profiling联合分析,请使用
--format=json回退到 JSON 格式。
使用方法
python trace_convert.py [-h] [--input INPUT] [--output OUTPUT] [--format FORMAT] [--profiling_data PROFILING_DATA] [--pid_mapping PID_MAPPING]
参数说明
| 参数 | 说明 | 示例值 | 默认值 |
|---|---|---|---|
--input |
输入的原始 trace 文件路径,通过 trace_record.py 生成 |
/path/to/trace_data.dat |
trace.dat |
--output |
输出的文件路径 | trace.db 或 trace.json |
ftrace_data.db |
--format |
指定输出的数据格式,支持 db 或 json |
json |
db |
--profiling_data |
同步采集的Profiling数据文件路径,用于时间轴对齐,以便导入MindStudio Insight联合分析 | /profiling/xxxx_ascend_pt |
- |
--pid_mapping |
容器场景下,可传入pid映射文件路径,进行容器与宿主机PID转换,详见容器内外PID命名空间隔离场景下采集 | pid_mapping.json |
- |
使用示例
假设第一步采集的profiling数据在目录result_dir/xxxx_ascend_pt下。
执行命令:
# --input默认为trace.dat
python trace_convert.py --profiling_data=result_dir/xxxx_ascend_pt
tracefs/debugfs模式使用
.txt文件作为输入时,需要显式指定输入文件,例如 --input=trace.txt 。
多卡场景下,--profiling_data可指定为包含多卡的上级目录,或任意单卡数据目录。
5. 容器内外PID命名空间隔离场景下采集
默认情况下(即容器启动时,未设置--pid=host参数),Docker容器有自己独立的PID命名空间。在容器中运行模型,profiling采集的进程号,为容器内部进程号。而ftrace采集的时Linux Kernel内核数据,与容器内进程号存在命名空间隔离,无法直接对齐。
针对该问题,trace_record.py脚本中提供了接口,用于获取容器内PID与宿主机PID的映射关系(基于遍历/proc/$PID/status文件的方式)。
方式一:命令行采集
- 使用
trace_record.py脚本采集ftrace数据时,打开--NSpid开关,得到pid_mapping.json交付件,记录了PID映射关系。 - 使用
trace_convert.py脚本进行数据后处理时,通过--pid_mapping参数,传入pid_mapping.json路径。脚本执行时,会自动将采集到的进程号转换为容器内进程号,以便于和profiling所采集进程号对应。
方式二:API接口采集模式
可单独使用 trace_record.py 脚本中的 ContainerPidMapper 类,提供以下对外接口:
1. 类构造函数
def __init__(self, output_file: str = "pid_mapping.json")
2. PID映射关系dump功能
// 开启接口
def start(self, duration=None)
// 停止接口
def stop(self)
说明:参数duration代表映射关系dump采集的开启周期,当传入None时,仅dump一次,且无需调用stop接口;传入其它有效值时,每duration秒dump一次,并通过stop接口停止。
采集样例:基于vllm-ascend场景的ftrace数据与profiling数据联合分析
本样例给出一个在Docker容器内基于vllm-ascend(v0.11.0)进行离线推理服务,同步采集Profiling数据,在宿主机通过命令行方式采集ftrace数据,并将采集结果导入MindStudio Insight进行联合分析的简单样例,帮助用户快速上手。
1. 前置准备
vllm-Ascend镜像获取地址:https://quay.io/repository/ascend/vllm-ascend?tab=tags
vllm-Ascend文档:https://docs.vllm.ai/projects/ascend/zh-cn/v0.11.0-dev/quick_start.html
按照文档所示,获取镜像,启动容器。
安装trace-cmd:
-
Ubuntu安装命令:sudo apt-get install trace-cmd
-
CentOS安装命令:sudo yum install trace-cmd
获取ftrace采集与转换脚本
下载本仓库提供的ftrace采集与转换脚本至本地。
├── ftrace_tools
│ ├── trace_convert.py
│ └── trace_record.py
环境变量配置:
# Load model from ModelScope to speed up download
export VLLM_USE_MODELSCOPE=True
# Set `max_split_size_mb` to reduce memory fragmentation and avoid out of memory
export PYTORCH_NPU_ALLOC_CONF=max_split_size_mb:256
# 开启vllm profiling采集(请根据实际需要指定profiling输出路径)
export VLLM_TORCH_PROFILER_DIR="/path/to/profiling/data"
# 开启绑核,将NPU 0 绑至CPU 0-15核
export CPU_AFFINITY_CONF=2,npu0:0-15
此处绑核仅为示例,请根据实际业务需要确定CPU绑核区间,建议采用NPU与CPU亲和性绑核。详见:绑核优化-Ascend Extension for PyTorch-昇腾社区
2. 进入容器,运行vllm-ascend离线推理任务,同步采集ftrace与Profiling数据
可参考以下推理脚本Qwen3_8B.py进行vllm-ascend离线推理任务,脚本将同步采集Profiling数据:
import os
from vllm import LLM, SamplingParams
prompts = [
"Hello, my name is",
"The future of AI is",
]
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
llm = LLM(
model="Qwen/Qwen3-8B",
max_model_len=26240
)
# 开启profiling采集
llm.start_profile()
outputs = llm.generate(prompts, sampling_params)
# 停止profiling采集
llm.stop_profile()
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")
请注意Profiling采集配置。当前仅支持ftrace与Text类型的Profiling联合展示,暂不支持与DB类型的Profiling数据联合展示。
在宿主机启动ftrace采集:
# 进入脚本所在目录
cd /home/xxx/msinsight/scripts/ftrace_tools
# record_time为-1代表持续采集,需Ctrl+C手动终止
# 针对CPU0-15核采集,打开容器内外PID映射开关
python trace_record.py --record_time=-1 --cpu=0-15 --NSpid
ftrace采集期间,同步在容器中运行推理脚本:
python Qwen3_8B.py
注意:--record_time为-1,代表持续采集模式,ftrace采集完成后,需及时Ctrl+C终止采集进程。
采集结果 vllm-ascend离线推理任务运行,profiling成功采集,打屏回显如下:
......
[INFO] [1070251] profiler.py: Start parsing profiling data: /home/tangke/result_dir/profiling0113/ubuntu122_1069691_20260113031336165_ascend_pt
[INFO] [1070260] profiler.py: CANN profiling data parsed in a total time of 0:00:06.039457
[INFO] [1070251] profiler.py: All profiling data parsed in a total time of 0:00:34.928982
Prompt: 'Hello, my name is', Generated text: ' Lucy and I am an 8 year old who loves to draw and write stories'
Prompt: 'The future of AI is', Generated text: ' a topic that has been widely discussed, with many people expressing both excitement and concern'
得到如下形式的profiling采集交付件:
.
└── profiling
└── ubuntu122_1069691_20260113031336165_ascend_pt
├── ASCEND_PROFILER_OUTPUT
├── FRAMEWORK
├── logs
├── PROF_000001_20260113031336168_JJIHFMPCABFRIEEB
├── profiler_info_0.json
└── profiler_metadata.json
ftrace采集成功打屏回显如下:
trace-cmd模式:
......
[2026-02-11 08:16:24,486] [INFO]:Ending record, cleaning up...
[2026-02-11 08:16:24,487] [INFO]:Stopping trace-cmd record process
[2026-02-11 08:16:28,488] [INFO]:trace-cmd record process stopped
[2026-02-11 08:16:28,488] [INFO]:Run command/usr/bin/trace-cmd clear
[2026-02-11 08:16:28,573] [INFO]:Run command/usr/bin/trace-cmd reset
[2026-02-11 08:16:30,912] [INFO]:Cleanup finished
tracefs/debugfs模式:
......
[2026-05-15 06:26:38,839] [INFO]:Ending record, cleaning up...
[2026-05-15 06:26:38,840] [INFO]:debugfs tracing disabled in 0.000s
[2026-05-15 06:27:22,020] [INFO]:debugfs trace snapshot copy finished: output=debugfs_5cpu_snapshot.txt, bytes=183936388, duration=43.180s
[2026-05-15 06:27:23,180] [INFO]:Trace data saved to debugfs_5cpu_snapshot.txt
[2026-05-15 06:27:23,180] [INFO]:Cleanup finished
得到如下形式的ftrace采集结果(默认保存在ftrace脚本同级目录下):
.
├── ftrace_tools
│ ├── trace.dat # trace-cmd record采集结果
│ ├── trace.txt # tracefs/debugfs模式采集结果,与trace.dat二选一
│ ├── pid_mapping.json #容器内外PID映射信息
│ ├── trace_convert.py
│ └── trace_record.py
3. 数据后处理
该步骤将原始 ftrace 数据转换为 Chrome Trace JSON 格式,并与所采集的profiling数据时间轴对齐,以便导入 MindStudio Insight 可视化工具联合展示与分析。
假设所采集的profiling数据在目录/path/to/profiling/xxxx_ascend_pt下。trace-cmd采集结果trace.dat与容器内外PID映射信息pid_mapping.json在trace_convert.py同级目录下。
执行命令:
# 进入脚本所在目录
cd /home/xxx/msinsight/scripts/ftrace_tools
# --input默认为trace.dat
python trace_convert.py --profiling_data=/path/to/profiling/xxxx_ascend_pt --pid_mapping=pid_mapping.json
多卡场景下,
--profiling_data可指定为包含多卡的上级目录,或任意单卡数据目录。
转换结果ftrace_data.db默认保存在当前目录下。可将其导入MindStudio Insight,进行可视化分析。
.
├── ftrace_tools
│ ├── trace.dat
│ ├── trace.txt
│ ├── ftrace_data.db # ftrace转换结果
│ ├── pid_mapping.json
│ ├── trace_convert.py
│ └── trace_record.py
4. 导入MindStudio Insight联合分析
注意:当前暂不支持Text类型数据与DB类型数据混合显示。若Profiling为Text和DB混合场景,需要提前删除其中的DB交付件
analysis.db与ascend_pytorch_profiler_x.db。
打开MindStudio Insight可视化软件,首先导入Profiling数据:

随后,在同一工程中导入ftrace数据:
即可联合分析Profiling数据与ftrace数据:

CPU Scheduling泳道,可从CPU视角查看进程调度情况。

Process Scheduling泳道,可查看特定进程的调度状态。

利用MindStudio Insight的泳道置顶功能,可以将感兴趣的泳道放在一起联合分析。

联合分析思路
一般而言,若在Profiling中观察到下发瓶颈点,可先通过CPU Scheduling泳道,概览性地观察该时间段内,下发流水中的热点线程,如Pytorch主线程、前向算子下发、反向算子下发、PTA二级流水下发(aclThread)等,是否存在进程抢占、软中断等情况。随后,观察特定进程的Process Scheduling泳道,进一步了解进程状态。最后,根据分析结果,进行针对性优化,例如改进绑核方案、核隔离、流水优化等。
tracefs/debugfs模式支持
部分用户的目标环境无法安装或使用 trace-cmd。为覆盖这类场景,trace_record.py 提供 tracefs/debugfs 后端,直接通过内核 tracing 文件系统配置 ftrace,并将采集结果保存为文本格式 trace 文件。
1. 启动采集命令差异
trace-cmd模式:
# --backend默认为auto,自动优先使用trace-cmd
python trace_record.py --record_time=30 --cpu=0-15 --output=trace.dat --NSpid
tracefs/debugfs模式:
# 未安装 trace-cmd 时 auto 会自动回退到 tracefs/debugfs;如需强制使用该模式,可显式指定 --backend=debugfs
python trace_record.py --backend=debugfs --record_time=30 --cpu=0-15 --output=trace.txt --NSpid
2. 转换命令差异
trace-cmd模式:
python trace_convert.py --input=trace.dat --output=tracecmd.json --profiling_data=/path/to/profiling/xxxx_ascend_pt --pid_mapping=pid_mapping.json
tracefs/debugfs模式:
# 需要显式指定--input。
python trace_convert.py --input=trace.txt --output=debugfs.json --profiling_data=/path/to/profiling/xxxx_ascend_pt --pid_mapping=pid_mapping.json
tracefs/debugfs模式的输出文件通常为
trace.txt。若同目录下仍存在默认文件名trace.dat,且转换时未显式指定--input=trace.txt,trace_convert.py可能会按默认输入读取trace.dat,导致转换的不是本次tracefs/debugfs采集结果。
3. 性能效率差异
tracefs/debugfs 后端输出文本格式 trace 文件,停止采集后的落盘耗时和后续 trace_convert.py 解析耗时会受 CPU 采集范围、事件量、业务负载和磁盘性能影响。采集范围较大或事件量较高时,耗时可能明显增加。
4. 采集结果对比
除输出格式和使用方式差异外,tracefs/debugfs 模式采集的事件范围与 trace-cmd 模式保持一致,转换后的可视化结果整体接近。
CPU Scheduling泳道对比
trace-cmd模式:

debugfs模式:

Process Scheduling泳道对比
trace-cmd模式:

debugfs模式:

常见问题FAQ
1. Profiling数据与ftrace数据联合导入失败,报错File Conflict

答: 当前暂不支持Text类型数据与DB类型数据混合显示。由于 ftrace 数据默认导出为 DB 格式,如果此时您导入的 Profiling 数据仅为 Text 类型,则会产生格式冲突。
解决方案:若 Profiling 为 Text 和 DB 混合场景,需要提前删除 Profiling 中的 DB 交付件 analysis.db 与 ascend_pytorch_profiler_x.db,并在转换 ftrace 数据时,使用 --format=json 回退到 JSON 格式。

2. 采集后ftrace数据部分CPU核存在大面积空白

可能性1:ftrace采用环形缓冲区,这意味着缓冲区满后新数据会覆盖旧数据,可以在脚本trace_record.py中调整缓冲区大小buffer_size,例如调整至--bf_size=4096',tracefs/debugfs模式建议调整至大于40960KB。
另外,当前脚本会在采集停止时读取tracefs per-CPU stats。如果日志中出现如下告警,说明本次采集过程中已经感知到环形缓冲区覆盖或事件丢失,建议增大--bf_size(优先)、缩短采集时长、减少采集事件或缩小CPU采集范围后重新采集。
tracefs stats report lost/overwritten events before reset: total_loss_counters=123. Consider increasing --bf-size
可能性2:该核在此时段没有目标事件,或未被业务实际使用(可能性较小)
3. trace-cmd record 停止超时
采集数据量较大时,trace-cmd record进程清理时间较长,超出了预设值范围。适当调大trace_record.py脚本中的_INT_INTERVAL_SEC与_WAIT_TIMEOUT_SEC参数即可。