这次我们来看 NVIDIA 新推出的 srt-slurm 框架这是一个专门为 SLURM 集群环境设计的声明式基准测试工具。如果你在 HPC 或 AI 训练环境中经常需要跑性能测试、对比不同配置的效果或者苦于每次手动编写复杂的 SLURM 脚本这个项目值得关注。srt-slurm 的核心思路很简单用 YAML 文件定义测试工作流自动生成可复现的 SLURM 作业。它解决了传统基准测试中的几个痛点配置散落各处、参数难以追溯、环境差异导致结果不可比。NVIDIA 推出这个工具明显是瞄准了大规模 GPU 集群的效能验证场景——无论是新卡上线、驱动更新还是框架升级都需要快速、标准化的性能评估。从实际使用角度看srt-slurm 最大的特点是声明式配置。你不需要手写 sbatch 脚本里那些资源申请、模块加载、任务分发命令只需要在 YAML 里声明测试目标、资源需求和执行步骤。框架会自动处理 SLURM 作业提交、依赖管理和结果收集。对于需要反复运行的基准测试比如每晚的回归测试这种自动化能节省大量时间。本文会带你完成 srt-slurm 的完整使用流程从环境准备、YAML 配置编写到实际提交测试、结果解读最后是常见问题排查。虽然这是个集群管理工具但我们在单节点 SLURM 环境也能验证基本功能。如果你有访问 SLURM 集群的权限建议直接跟着操作一遍。1. 核心能力速览能力项说明项目类型SLURM 基准测试自动化框架开源团队NVIDIA 系统软件团队核心功能通过 YAML 配置生成可复现的 SLURM 工作流资源需求需要 SLURM 集群环境GPU/CPU 资源按测试需求配置配置方式声明式 YAML支持参数化模板输出结果标准化性能数据、日志文件、作业状态报告适合场景HPC 性能测试、AI 训练基准对比、集群效能评估srt-slurm 不是独立的执行引擎而是 SLURM 的上层工具。它生成的仍然是标准 SLURM 作业所以兼容性取决于你的集群配置。如果你能在集群上正常使用sbatch、squeue命令就能用这个框架。2. 适用场景与使用边界srt-slurm 最适合需要重复执行的性能基准测试。比如以下几种情况典型使用场景新硬件验收在新 GPU 节点加入集群后运行标准测试套件验证性能是否符合预期软件栈升级验证更新 CUDA、PyTorch、TensorFlow 后对比训练速度变化资源配置优化测试不同 GPU 数量、CPU 核数、内存大小对任务性能的影响长期性能监控定期运行基准测试监控集群性能衰减或异常不适合的场景单次临时任务如果只是偶尔跑一个作业直接写 sbatch 脚本更直接非 SLURM 环境该框架依赖 SLURM 工作流其他调度器如 PBS、K8s无法使用交互式开发不适合需要实时交互的调试任务重要边界测试任务必须合法合规避免占用过多集群资源影响他人性能测试可能涉及商业软件许可确保有相应授权敏感数据或模型需遵守所在机构的保密规定3. 环境准备与前置条件在使用 srt-slurm 前需要确保基础环境就绪。由于这是集群工具很多检查需要在登录节点或计算节点上进行。3.1 SLURM 集群访问验证首先确认你能正常使用 SLURM 命令# 检查 SLURM 状态 sinfo # 查看可用分区 sinfo -s # 查看当前作业 squeue -u $USER如果这些命令报错或提示无权限需要联系集群管理员开通账户。3.2 Python 环境要求srt-slurm 需要 Python 3.7 环境。建议使用 conda 或 venv 创建独立环境# 创建并激活 conda 环境 conda create -n srt-slurm python3.9 conda activate srt-slurm # 或者使用 venv python -m venv srt-slurm-env source srt-slurm-env/bin/activate3.3 依赖包安装除了 srt-slurm 本身还需要确保测试任务所需的软件包可用。常见的 AI 训练基准测试会用到# 示例安装 PyTorch 相关依赖 pip install torch torchvision torchaudio pip install numpy pandas matplotlib # 安装 srt-slurm pip install srt-slurm3.4 存储空间检查基准测试通常会产生大量日志和结果数据确保你的工作目录有足够空间# 检查磁盘使用情况 df -h $HOME df -h /scratch # 如果使用临时存储4. 安装部署与启动方式srt-slurm 的安装相对简单主要是 Python 包管理。重点在于理解它的工作目录结构。4.1 安装方法# 从 PyPI 安装稳定版 pip install srt-slurm # 或者从源码安装最新版 git clone https://github.com/nvidia/srt-slurm cd srt-slurm pip install -e .4.2 验证安装安装完成后检查命令行工具是否可用srt-slurm --help应该看到类似输出Usage: srt-slurm [OPTIONS] COMMAND [ARGS]... Options: --version Show the version and exit. --help Show this message and exit. Commands: generate Generate SLURM jobs from YAML configuration run Run generated SLURM jobs report Generate reports from job results4.3 项目目录结构建议为每个基准测试项目创建独立目录my-benchmark/ ├── config.yaml # 主配置文件 ├── templates/ # 任务模板目录 │ ├── training.j2 # 训练任务模板 │ └── inference.j2 # 推理任务模板 ├── scripts/ # 辅助脚本 │ └── setup_env.sh # 环境设置脚本 ├── inputs/ # 输入数据 ├── outputs/ # 输出结果 └── logs/ # 日志文件5. YAML 配置详解srt-slurm 的核心是 YAML 配置文件。我们来拆解一个完整的示例理解各个配置段的作用。5.1 基础结构# config.yaml name: gpu-training-benchmark description: GPU训练性能基准测试 version: 1.0 slurm: partition: gpu-partition account: my-project time: 02:00:00 qos: normal environment: variables: CUDA_VISIBLE_DEVICES: 0,1,2,3 NCCL_DEBUG: INFO modules: - cuda/11.8 - gcc/9.3.0 - openmpi/4.1.1 resources: gpu: type: a100 count: 4 cpu: count: 32 memory: 128G workflow: - name: data-preparation type: preprocessing script: scripts/prepare_data.py - name: training-benchmark type: training script: scripts/run_training.py depends_on: [data-preparation] - name: inference-test type: inference script: scripts/run_inference.py depends_on: [training-benchmark]5.2 SLURM 参数配置slurm段对应 sbatch 脚本的常用参数slurm: partition: gpu-partition # 计算分区 account: my-project # 项目账户 time: 02:00:00 # 最大运行时间 qos: normal # 服务质量 constraint: a100 # 节点约束 reservation: my-reservation # 资源预留 exclusive: true # 独占节点5.3 环境设置environment段定义任务执行环境environment: setup_script: scripts/setup_env.sh # 环境初始化脚本 variables: # 环境变量 CUDA_VISIBLE_DEVICES: 0,1,2,3 NCCL_DEBUG: INFO OMP_NUM_THREADS: 4 modules: # 要加载的环境模块 - cuda/11.8 - gcc/9.3.0 - openmpi/4.1.1 conda_env: my-benchmark-env # Conda 环境名5.4 工作流定义workflow段定义任务依赖关系支持复杂的 DAG有向无环图workflow: - name: stage-1 type: preprocess script: scripts/stage1.py resources: gpu: 1 cpu: 8 memory: 32G - name: stage-2 type: process script: scripts/stage2.py resources: gpu: 2 cpu: 16 memory: 64G depends_on: [stage-1] # 依赖前一个任务 - name: stage-3 type: analysis script: scripts/stage3.py resources: cpu: 4 memory: 16G depends_on: [stage-2] # 依赖前一个任务6. 任务模板与参数化srt-slurm 支持 Jinja2 模板可以实现配置的参数化避免重复编写相似任务。6.1 基础模板示例创建templates/training.j2#!/bin/bash #SBATCH --job-name{{ job_name }} #SBATCH --partition{{ partition }} #SBATCH --account{{ account }} #SBATCH --time{{ time }} #SBATCH --gresgpu:{{ gpu_count }} #SBATCH --cpus-per-task{{ cpu_count }} #SBATCH --mem{{ memory }} # 加载环境模块 {% for module in modules %} module load {{ module }} {% endfor %} # 设置环境变量 {% for key, value in environment.items() %} export {{ key }}{{ value }} {% endfor %} # 运行训练脚本 python {{ script_path }} \ --epochs {{ epochs }} \ --batch-size {{ batch_size }} \ --learning-rate {{ lr }} \ --output-dir {{ output_dir }}6.2 参数化配置在主配置中引用模板并传递参数# config.yaml templates: training-template: templates/training.j2 parameters: batch_sizes: [32, 64, 128] learning_rates: [0.001, 0.0001] workflow: - name: training-{{ bs }}-{{ lr }} template: training-template parameters: bs: {{ batch_size }} lr: {{ learning_rate }} matrix: # 参数矩阵生成多个任务 batch_size: [32, 64, 128] learning_rate: [0.001, 0.0001]6.3 条件执行模板支持条件逻辑适合复杂的工作流{% if gpu_count 1 %} # 多GPU训练设置 export CUDA_VISIBLE_DEVICES0,1,2,3 python -m torch.distributed.launch --nproc_per_node{{ gpu_count }} \ {{ script_path }} --distributed {% else %} # 单GPU训练 export CUDA_VISIBLE_DEVICES0 python {{ script_path }} {% endif %}7. 执行与监控配置完成后实际执行流程分为生成、提交、监控三个阶段。7.1 生成 SLURM 作业# 生成作业脚本 srt-slurm generate config.yaml # 指定输出目录 srt-slurm generate config.yaml --output-dir generated_jobs生成的文件结构generated_jobs/ ├── job_1_data_preparation.sh ├── job_2_training_benchmark.sh ├── job_3_inference_test.sh ├── dependencies.json └── workflow_graph.png7.2 提交作业# 提交整个工作流 srt-slurm run generated_jobs/ # 只提交特定任务 srt-slurm run generated_jobs/ --job-names training-benchmark # 干跑模式只显示会提交的作业 srt-slurm run generated_jobs/ --dry-run7.3 监控执行状态srt-slurm 提供状态监控工具# 查看工作流状态 srt-slurm status generated_jobs/ # 持续监控 srt-slurm monitor generated_jobs/ --interval 30 # 查看详细日志 tail -f generated_jobs/logs/training-benchmark.log同时可以使用原生 SLURM 命令监控# 查看所有作业状态 squeue -u $USER -o %.10i %.20j %.10T %.10M %.10l %.6D %.20R # 查看特定作业详情 scontrol show job job_id8. 结果收集与分析基准测试的价值在于结果分析。srt-slurm 提供了结果收集和报告生成功能。8.1 结果文件结构任务执行完成后输出目录通常包含outputs/ ├── training-benchmark/ │ ├── metrics.json # 性能指标 │ ├── system_stats.csv # 系统统计 │ ├── model_checkpoint.pth # 模型文件 │ └── logs/ │ ├── stdout.log # 标准输出 │ └── stderr.log # 标准错误 ├── inference-test/ │ └── latency_results.json └── summary_report.html8.2 生成汇总报告# 生成文本报告 srt-slurm report outputs/ --format text # 生成HTML报告 srt-slurm report outputs/ --format html --output report.html # 生成对比报告多个测试结果 srt-slurm report output1/ output2/ output3/ --format html8.3 自定义指标提取你可以编写自定义分析脚本处理结果# analyze_results.py import json import pandas as pd from pathlib import Path def extract_training_metrics(output_dir): metrics [] for result_file in Path(output_dir).glob(*/metrics.json): with open(result_file) as f: data json.load(f) data[job_name] result_file.parent.name metrics.append(data) df pd.DataFrame(metrics) return df # 使用示例 df extract_training_metrics(outputs/) print(df[[job_name, throughput, accuracy, training_time]])9. 高级功能与最佳实践掌握了基础用法后来看几个提升效率的高级功能。9.1 参数扫描与优化srt-slurm 非常适合超参数搜索parameters: batch_sizes: [32, 64, 128, 256] learning_rates: [0.1, 0.01, 0.001, 0.0001] optimizers: [sgd, adam, adamw] workflow: - name: hparam-search-{{ bs }}-{{ lr }}-{{ opt }} template: training-template matrix: batch_size: [32, 64, 128, 256] learning_rate: [0.1, 0.01, 0.001, 0.0001] optimizer: [sgd, adam, adamw] resources: gpu: 1 time: 01:00:009.2 错误处理与重试配置自动重试机制提高稳定性workflow: - name: critical-training script: scripts/train.py retry_policy: max_attempts: 3 backoff_factor: 2 on_failure: continue # 或 stop_workflow9.3 资源弹性分配根据任务类型动态调整资源workflow: - name: data-heavy-task script: scripts/process_data.py resources: gpu: 0 cpu: min: 8 max: 32 memory: min: 32G max: 128G scaling_policy: memory_bound # 根据内存需求调整10. 性能优化技巧在大型集群上运行基准测试时这些优化能显著提升效率。10.1 任务并行化利用 SLURM 的作业数组功能workflow: - name: parallel-tasks-{task_id} script: scripts/parallel_task.py array: count: 10 max_concurrent: 4 # 同时运行的任务数10.2 数据局部性优化确保计算节点能快速访问数据environment: variables: DATA_DIR: /scratch/$USER/data # 使用本地临时存储 workflow: - name: stage-data script: scripts/stage_data.py resources: node_local_storage: /scratch # 要求节点有本地存储10.3 资源使用监控实时监控资源使用情况避免浪费# 监控GPU使用 watch -n 1 nvidia-smi # 监控内存使用 sacct -j job_id --formatJobID,Start,End,Elapsed,MaxRSS,State11. 常见问题与排查方法在实际使用中可能会遇到各种问题这里总结典型场景的解决方案。问题现象可能原因排查方式解决方案作业一直处于 PENDING 状态资源不足、分区限制、优先级低squeue -o %.10i %.20j %.10T %.10Q %.20R检查分区配置、账户限制、资源请求合理性作业失败且无错误信息环境配置问题、脚本权限查看作业日志cat slurm-job_id.out检查环境模块、Python路径、脚本执行权限依赖任务失败导致后续任务不执行前序任务非正常退出scontrol show job job_id查看退出码调整依赖策略或添加重试机制GPU 无法识别或显存不足驱动问题、GPU类型不匹配nvidia-smi验证GPU状态检查CUDA版本、GPU约束条件任务超时被杀死时间估计不足、死循环查看作业时间限制scontrol show job job_id合理估计运行时间添加检查点内存不足被杀死内存估计不足、内存泄漏查看最大内存使用sacct -j job_id --formatMaxRSS增加内存请求或优化程序内存使用11.1 详细排查流程作业提交失败# 1. 检查SLURM配置 scontrol show partition # 2. 检查账户权限 sacctmgr show user $USER # 3. 验证资源可用性 sinfo -p gpu-partition -o %P %a %l %D %A任务执行错误# 1. 查看详细错误信息 cat slurm-job_id.out cat slurm-job_id.err # 2. 检查环境加载 which python python --version module list # 3. 验证数据访问 ls -la $DATA_DIR12. 实际案例AI训练基准测试通过一个完整的AI训练基准测试案例展示srt-slurm的实际应用价值。12.1 项目背景假设我们要评估新采购的A100 GPU集群在典型AI工作负载下的性能测试包括ResNet-50图像分类训练BERT文本分类微调Transformer机器翻译训练12.2 配置文件设计# ai-benchmark.yaml name: ai-training-benchmark description: A100集群AI训练性能评估 slurm: partition: a100-partition account: ai-research time: 04:00:00 parameters: models: resnet50: script: scripts/train_resnet.py dataset: imagenet bert: script: scripts/finetune_bert.py dataset: glue transformer: script: scripts/train_transformer.py dataset: wmt14 workflow: - name: prepare-{{ model }}-data script: scripts/prepare_data.py parameters: model: {{ model }} dataset: {{ dataset }} - name: train-{{ model }} template: training-template parameters: model: {{ model }} script: {{ script_path }} depends_on: [prepare-{{ model }}-data] matrix: model: [resnet50, bert, transformer]12.3 执行与结果分析# 生成作业 srt-slurm generate ai-benchmark.yaml # 提交执行 srt-slurm run generated_jobs/ # 监控进度 srt-slurm monitor generated_jobs/ --interval 60 # 生成报告 srt-slurm report outputs/ --format html12.4 关键性能指标测试完成后重点关注这些指标训练吞吐量images/sec 或 tokens/secGPU利用率nvidia-smi 中的 Volatile GPU-Util显存使用峰值显存占用收敛速度达到目标精度所需的epoch数多机扩展效率多GPU时的加速比13. 集成与扩展srt-slurm可以与其他工具集成构建完整的CI/CD流水线。13.1 与版本控制集成将配置和脚本纳入Git管理# 典型的项目结构 ai-benchmarks/ ├── .gitignore ├── README.md ├── configs/ │ ├── base.yaml │ ├── gpu-benchmarks.yaml │ └── cpu-benchmarks.yaml ├── scripts/ │ ├── training/ │ └── inference/ ├── templates/ └── results/ # 不纳入版本控制13.2 与CI系统集成在GitLab CI或GitHub Actions中自动运行基准测试# .gitlab-ci.yml benchmark: script: - pip install srt-slurm - srt-slurm generate configs/benchmark.yaml - srt-slurm run generated_jobs/ - srt-slurm report outputs/ --format html artifacts: paths: - outputs/ - report.html13.3 自定义插件开发srt-slurm支持插件机制可以扩展功能# custom_plugins/my_analyzer.py from srt_slurm.plugins import ResultAnalyzer class MyResultAnalyzer(ResultAnalyzer): def analyze(self, job_results): # 自定义分析逻辑 return analysis_reportsrt-slurm 的价值在于将临时性的性能测试转变为可重复、可追溯的工程实践。虽然初期需要投入时间学习YAML配置和模板语法但一旦建立起标准流程后续的测试工作会变得异常高效。对于刚接触的团队建议从简单的单任务测试开始逐步扩展到复杂的工作流。重点要建立结果数据的标准收集格式这样才能进行有意义的纵向对比。当配置稳定后可以考虑将srt-slurm集成到日常的CI流程中实现自动化的性能回归测试。在实际使用中最容易出现的问题是环境差异导致的结果不可比。务必确保每次测试的基础环境驱动版本、软件包、数据集保持一致。另外SLURM集群的负载状况也会影响性能数据尽量在相对空闲的时间段运行关键基准测试。
企业数字化 ERP 产品动态
相关推荐
BERT与LLM协同优化:低成本部署与性能提升实战 1. 为什么BERT能成为大模型的"僚机"?在自然语言处理领域,大语言模型(LLM)和BERT这类预训练模型各有所长。LLM擅长生成连贯的文本和复杂推理,而BERT在理解上下文和提取语义特征方面表现优异。这种互补性正是构建高效智能体系统的关键… · 2026/11/14 3:58:48
Java开发者转型大模型应用:LangSmith工具链实践指南 1. 从Java开发者到大模型应用工程师的转型之路作为一名有十年Java开发经验的程序员,当我第一次接触大模型应用开发时,那种既熟悉又陌生的感觉至今难忘。Java世界的严谨架构设计与AI领域的灵活创新形成了鲜明对比,而LangSmith作为大模型应用开… · 2026/11/10 9:04:54
电工证哪个部门发放真实经历:外省证怎么转回来 电工证哪个部门发放真实经历:外省证怎么转回来 之前考的证在外省能不能转过来?这个问题我真见过太多人问,我自己也是从河南安阳考的电工证,后来在外地工作了几年,回来后才发现证转回来不是那么简单。今天就来聊一聊【电工证哪个部门发放】这个事儿,结合… · 2026/11/14 3:58:43
值班电工证有效多久网上查询攻略:工地太忙根本没时间复习考试 值班电工证有效多久网上查询攻略:工地太忙根本没时间复习考试 工地太忙根本没时间复习考试,尤其是对于刚转岗的新乡从业者来说,一边要忙着应对高强度的工作节奏,一边还得抽空准备电工证的考试和复审,真的让人头大。很多人一听到“值班电工证有效多久”这… · 2026/11/14 3:58:43
深圳平湖电工证多少钱电子证书怎么考 深圳平湖电工证多少钱电子证书怎么考 实操考试心里没底怕挂科,尤其是第一次考电工证的朋友,面对高压电、工具操作、电路图识别这些内容,光是想想就紧张。别慌,深圳平湖电工证多少钱,怎么顺利考过,我给你整明白。… · 2026/11/14 3:58:43
单位电工证可以再考吗保姆级教程:外省证怎么转过来?别再被坑了 单位电工证可以再考吗保姆级教程:外省证怎么转过来?别再被坑了 之前考的证在外省能不能转过来?这个问题几乎每个在工地干过的电工都问过,尤其是像你这样在信阳做建筑工的兄弟,手里拿着外地电工证,生怕哪天用不了。别急,今天这波保姆级教程,教你一步步… · 2026/11/14 3:58:43
揭阳市低压电工证打印ic卡怎么考?上岗必备的避坑指南 揭阳市低压电工证打印ic卡怎么考?上岗必备的避坑指南 怕考不过白交培训费?揭阳市低压电工证打印ic卡是很多电工岗位的上岗必备,但很多人在备考时容易踩坑,尤其是对考试内容、题型分布、复习方法不熟悉,结果花了几千块培训费,最后还是没通过考试。今… · 2026/11/14 3:58:43
天津考电工证北辰千万别踩坑 电工证怎么考才不亏 天津考电工证北辰千万别踩坑 电工证怎么考才不亏 怕考不过白交培训费?你不是一个人。天津北辰区想考电工证的朋友,别再随便报班了,一不小心就踩坑,不仅钱打水漂,还耽误时间。尤其是像你这样在开封水利工程上班的,想转行或提升收入,… · 2026/11/14 3:57:43
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/13 22:30:50
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/13 5:40:45
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/12 23:27:43
有初级电工证怎么工作 2026河南最新政策怎么应对 有初级电工证怎么工作 2026河南最新政策怎么应对 之前考的证在外省能不能转过来?这个问题我每天被问上百次。2026年河南最新政策对证书跨省转移有了明确说明,特别是南阳市的从业者,需要特别关注。… · 2026/11/14 0:00:31
电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 证书过期了不知道怎么复审延期?很多人遇到这种情况,要么是工作太忙没时间处理,要么是不知道具体流程,导致证书失效,影响工作和项目进展。其实复审并不难,关键是要找准官方报名入口,掌… · 2026/11/14 0:00:31
为什么要低压电工证实操考试考什么 为什么低压电工证值不值得考?别再被中介骗了 你是不是也经常看到网上有人在问“低压电工证到底值不值得考”?或者在找报名点时,担心被中间人骗钱?这些问题,我懂,我也经历过。作为一名在应急管理行业摸爬滚打多年的从业者,我深知低压电工证不仅是一个从… · 2026/11/14 0:00:31
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:12:21
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:11:51
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 22:31:30