agentleFS
brilliantroughbrilliantrough/agent-skills/skills/research/pytorch-perf-tuning/SKILL.md

pytorch-perf-tuning

Skill11 starsChanged 13 days agoMITView on GitHub

为 PyTorch 算法研究减少等待:诊断低吞吐、设备利用率与显存浪费,按预算优化并判断何时收口。Use before small-dataset evaluation sweeps or when PyTorch is slow;触发词:小数据集批量预研、审视PyTorch代码、设备吃不满、利用率低、矩阵太小、长输入测速、双卡流水线、评测太慢、显存不够、按模型shape写核、停止效率焦虑、还要不要优化。目标是研究迭代够快,不是硬件满载或穷尽调优。环境安装用 accel-pytorch-python,平台移植用 accel-pytorch-code-porting,单点故障用 diagnosing-bugs。

The file

Files
SKILL.md

PyTorch 算法迭代加速:够用即收口

遵循 goal-first:主线是算法结论,性能优化用于减少等待。去重、batch、grouped、融合核、流水线是按需手段,不是每个项目都要走完的毕业清单;先达到研究需要就停,不因仍有优化空间而延长任务。

0. 边界与成功标准

  • 成功标准:已知明显浪费得到处理,正确性/复现通过,实际等待能支持当前研究节奏;不设统一利用率、功率或加速倍数门槛。
  • 默认只改执行路径;模型结构、dtype、样本、评分协议保持,浮点差异按预定容差判断。
  • batch/padding/定标/算法变化单独对照;伪量化换真量化或整数 kernel 是数值与部署语义变化,不能冒充同口径加速。
  • 同阶段联合记录:有效吞吐/host耗时、设备忙碌度、功率、设备内存及 allocated/reserved 峰值;局部算子另用 Event。指标定义、窗口和设备映射一并保留。
  • 按剩余运行次数×单次可节省时间,粗估是否值得投入开发、验收、维护与注意力;加载、逐配置准备/编译也计入。给短预算,深度引擎/工具研发另设目标。

1. 拆时间:不要猜

  • 新执行路径先快速巡检无用计算、内存副本、batch、串行、同步/搬运及连续小操作,再按测量深入;覆盖检查视角,不逐项跑实验。批量预研也适用,已有就绪证据可复用。
  • 用小固定输入区分加载、准备、warmup、在线循环和评分耗时;先找可行动热点。
  • 局部算子先复用项目已验证的设备计时器:明确stream、依赖、预热、调用次数与统计量。首尾一对Event包住一批调用,再除以次数;100次是可用起点,不是所有任务的固定合同。
  • 测几轮保留原始值。普通Event窗口可能包含设备执行与队列空隙,不是纯host成本;必要时补dummy或图重放对照,各口径分别报告,不用异步host下发时长替代设备执行。
  • 定向计时仍定位不清才用 profiler,重点看 host 空白、密集小 kernel、memcpy;不默认收集重型计数器。
  • 确认物理设备、进程和其他作业后,在代表性评分窗口旁路低频采样利用率/功率/内存;不把加载、编译和在线阶段混成一个均值,不在热循环插同步监控。
  • 结论分为“可避免浪费/当前口径下合理受限/证据不足”,给出依据;定位到可行动热点即可,不把忙碌度或功率满格当完成条件。
  • 大矩阵压测只能校验持续负载能力;低AICore不等于整卡空闲,长输入也不保证更高有效吞吐。只有这会改变判断时,按references/device-observation.md做有界规模对照。

2. 先删:不需要的 tensor 和计算

项目默认处置
纯评测的梯度/反向图model.eval() + torch.inference_mode();训练及需梯度的校准保留计算图
纯打分 KV cacheuse_cache=False;生成/decode 才开
全词表 logits先选需要的位置再做 log_softmax;logits_to_keep
隐藏态/attention 输出不请求 output_hidden_states/attentions
超长 padding按实际长度截断;动态 padding/分桶
离线准备校准、量化、tokenize、编译一次,落盘缓存
未使用输出/中间量不保存;不要用输出对象长期持有 cache
训练显存activation checkpointing 换显存;eval 不需要
  • 纯打分关闭 KV 后验证 logits 逐位或容差一致;生成路径不能关。
  • 完成判据:峰值分配下降,输出对齐;没有把“少算”混进精度结论。

3. 去重:权重和常驻内存只留一份

  • 纯评测时释放确实不再需要的权重副本,必要时在 no-grad 下 weight.copy_(converted);训练的 master weights、优化器状态或后续需恢复的原权重不能随意删。
  • 打包/转置/分组权重与原 Parameter 共享 storage;不要 stack 后再整份复制。
  • 后续需原位修改的持久packed权重,在torch.inference_mode(False)下创建及绑定切片;外层推理上下文可能把它变成inference tensor,之后仅no_grad不能解除写入限制。
  • 按 (device, tensor.untyped_storage().data_ptr()) 去重,再加 storage 的 nbytes();切片的 tensor data_ptr() 可不同,不能据此判成多份权重。
  • 区分必要驻留、冗余活张量、allocated 与 reserved;reserved−allocated 含可复用缓存和碎片,不能直接算“死内存”。empty_cache() 只在阶段边界按需使用。
  • 大临时张量用完 del;检查 closure、hook、cache、profiler 是否还引用。
  • 完成判据:必要权重一份、冗余驻留减少;用余量提高有效 batch 或降低峰值,不以显存占用高低直接判断好坏。

4. Batch:先找吞吐拐点

  • batch 1 不是容量上限。从现有 batch 附近试少量候选,记录 tokens/s 与峰值;收益够用就停,不追最大容量或完整曲线。
  • 变长输入按长度排序/分桶,减少 padding;必要时用 varlen 算子。
  • 检查 batch 是否改变语义:动态定标/校准、padding 统计、归约顺序、RNG、样本分组。
  • 要保原口径就逐样本统计或固定校准;否则把 batch 变化单独记为协议变更。
  • 完成判据:少量吞吐对照 + 选定 batch + 对精度/定标影响的说明。

5. 串行 → 批量/分组/融合

  • 症状:Python for 逐 expert/head/segment 调小矩阵乘;每项一次 launch,设备吃不饱。
  • 做法:排序/分组后用框架或厂商 grouped GEMM;共享输入投影合并(QKV、gate_up)。查实际设备dispatch/短trace,接口叫grouped或fused仍可能内部逐项展开。
  • 固定形状+mask可代替ragged动态索引;reduce/scatter/index回退时补零可能更快,但最大路由容量会放大所有组的缓冲区。实测时间与峰值,不能一律改成稠密补零。
  • 独立分支才考虑多 stream;小算子并行会被 launch 开销吃掉。
  • 完成判据:单模块小 kernel 数下降,端到端同输入加速,数值一致。

6. 减少阻塞热路径的同步

异步执行中,以下操作可能让CPU等待设备;是否阻塞以实际后端和时间线为准:

类型例子处置
取值.item()、.cpu()、.tolist()、.numpy()移出循环,批量/结束后一次
布尔控制流if tensor、bool(tensor)改张量运算;仅 tensor > 0 生成张量本身不要求 host 取值
动态形状nonzero()、unique()、单参数 torch.where(mask)固定形状 + 三参数 where / 排序分组
显式同步synchronize()、empty_cache()只在阶段边界
隐式print(tensor)、assert tensor...、逐项日志删除或延迟
搬运循环内 .to(device)、.cpu()预取、pin memory、non_blocking
  • 保留正确性所需的依赖/同步;每层一次max().item()可能可接受,按时间线判断是否造成主要空白。
  • 能累计的指标放设备端,必要日志降低取值频次;不用逐步取回loss/acc制造等待。
  • 完成判据:主要同步点改善、结果不变、端到端变快;不追求消灭全部 host gap。

7. 算子、后端、编译

  • 将 SDPA/flash attention、fused optimizer、厂商库、torch.compile 作为现成候选;不要求全部试遍才准写融合核。
  • 在目标设备实测;CUDA 文档不代表 NPU,CPU 能跑不代表设备快,反之亦然。
  • 检查 fallback:一个 op 回退 CPU 可能比补零/稠密实现更慢。
  • dtype/layout:BF16/FP16、channels-last、contiguous;避免每步 transpose + contiguous。
  • CUDA graphs / graph mode 只在静态 shape、收益明确时。
  • 高频连续 PyTorch 片段(逐元素、广播、归约组合)可生成融合核;保留高效库边界,比较原链、融合核、接回原调用链的完整片段。
  • 完成判据:主导算子被处理,端到端变快,数值在容差内。

小核计时:先分清窗口

  • host下发跟不上时,plain Event会包含核间空等;小核的设备工作量不能直接由此推断。
  • dummy法在同一stream的start之前排入足够长的作业,让host有时间提交目标批次;须实测覆盖裕量,并注明dummy改变缓存/频率的可能影响,不能照搬固定matmul次数。
  • plain/dummy较大提示下发影响,但不是通用瓶颈阈值,也不证明设备优化无价值;dummy与graph都不等于普通调用的端到端收益。
  • 专业计量与可用计时器按独立kernel-knowledge的pipeline读取,定位见kernel-worker/references/kernel-knowledge.md。缺该库时沿用项目可信计时器并声明口径,不自动安装;不要重复维护其实现。

Agent 按模型/shape 生成与迭代 kernel

  • 区分变化的离线算法和可复用的在线原语。scale、旋转矩阵或权重变了,不意味着量化/反量化核也必须重写。
  • 从目标模型实际运行采集 shape、dtype、stride、归约轴、mask/分组及调用频次;围绕实测热点确定融合片段。
  • 按计算形态分核,再对模型的 shape 族生成或调参;允许不同实现和 tile,不强求一个接口或一套最优参数覆盖所有模型。
  • 跨模型复用公式、正确基线、候选源码和优化经验;适配后在新模型验证,已有同形态实现可直接作为候选,不必从零重写。
  • 热点独立、参考/回放/接口明确时,按 kernel-worker 填任务 brief 并显式调用宿主子 Agent,在独立工作区开发;主会话负责语义、资源预算、接入与整模验收。
  • 正确基线 → 少量相关方向,各试少数候选 → 逐次校验 → 同卡 A/B/B/A → 保留或回退。每次只改一类因素;收益已明确就收口,不为小幅增益反复爬坡。
  • 固定参考与样本;逐值比对舍入边界、尾块、统计分组和真实层输入。训练另验 backward/STE。
  • 专业实现、计量与平台经验优先复用可选kernel-knowledge;Atrex等外部引擎仅在后端/evaluator与预算就绪时调用。发现与缺失处理见kernel-worker/references/kernel-knowledge.md,研究任务取舍见references/kernel-decision.md;不把平台建设混进日常。

8. 多卡:区分放置与调度

  • 显式设置可见设备;device_map分层驻留主要分担存储,不自动启用张量并行或流水线。两卡轮流忙与两卡共同空白分别查,不能只因用了多卡就认定通信是主因。
  • 模型须跨卡时,可让不同完整batch在前后阶段重叠;优先保留已有分桶/定标,不先拆小batch。线程先做有界验证,确有下发瓶颈再考虑独立进程。
  • 阶段设备、Event依赖、源tensor寿命和线程上下文显式处理;先验证阶段串行与原模型,再比较同切分串行/重叠。细节见references/multi-device-pipeline.md。
  • DataLoader:workers、pin_memory、non_blocking、prefetch;CPU 预处理不要阻塞设备。
  • 允许模型副本时eval可按独立样本分片;训练用合适的DDP/FSDP等。根据容量、依赖和目标选并行方式,不要求试遍;遵守本任务已限定的方向。
  • 分钟级探针直接 Bash + Python,保存日志即可;确有跨小时生命周期问题时才按项目约定托管,不为小实验创建服务。
  • 完成判据:同口径有效吞吐和端到端时间改善,利用率/功率解释设备行为;不是“进程还活着”或硬件读数更高。

9. 验证与报告

  • 同输入、同 warmup,少量交错复测(如 A/B/B/A)确认收益;稳定后不追加重复。小时级全量用一次同输入对照,说明没有重复。
  • 数值按约定逐位/容差核对,任务响应逐项配对;总分相同不证明逐题一致。batch/定标变化单独标注,不能算无损。
  • 记录版本、设备、batch、dtype、峰值、命令;失败尝试也保留。
  • 单层/单模块倍数不外推整模;用真实模型同输入对照。
  • 分散分支的GMM、融合核、流水线收益不能相乘;接到共同入口后做有界同输入验收,采用已验证组合。
  • 整模验收用host时钟记录完整流程,边界等待相关设备;加载、准备、冷编译和稳态分列。设备微基准不代替整模验收。
  • 一次性JIT不能混进稳态比较,也不能从冷启动端到端中无声删除:分别报告冷启动与明确预热后的稳态。只有确认首样本承担编译并预先声明排除规则时,才单列该样本;不能因为它慢就丢弃,实际调用量还要覆盖编译成本。
  • 完成判据:别人能按记录复现,且知道哪一部分是协议变化。

10. 停止效率焦虑:冻结可用路径

  • 正确、收益可信、等待已够用:固定版本与配置,回算法研究;剩余可优化点和低利用率不是未完成项。也允许更早以参考路径收口,不必先写核或做流水线。
  • 预算耗尽或下一步成本超过可预见的等待节省:保留当前可靠实现,停止本轮;不自动换热点、换后端或另造引擎继续耗时。
  • 有界整合已有成果属于交付;整合中的正确性问题必须修复,不顺手开展新一轮性能研发。
  • 仅新模型/新路径异常慢、OOM/退化、等待重新阻塞具体研究,或有明确低成本收益时重开;“监控还没满”本身不触发。
  • 专业推理引擎也不保证所有负载满载。算法研究兼顾修改便利、数值透明和维护成本;性能专项若成为目标,单独约定,不默认升级当前任务。

反模式

  • 没测量就改;一次改五处;把清单全做一遍或把监控刷满当交付,挤占算法研究。
  • 把 batch 1 当容量上限;把 reserved 当泄漏;只凭利用率/功率/显存高低判代码质量。
  • 转换/量化时保留多份权重;为“以后”加抽象;为了覆盖所有模型强做大一统 kernel。
  • 因离线算法在变就否定共享在线核;用 FLOP 比猜耗时;没有参考实现就改舍入语义;未经对照就重写厂商 matmul。

参考

  • references/device-observation.md:轻量硬件观测与判断;references/checklist.md:按需代码排查、计时和内存模板。
  • references/multi-device-pipeline.md:跨完整batch重叠、上下文与依赖、数值/时间线/host验收。
  • references/case-moe-eval.md:去重、batch、原生GMM、流水线与输入规模的分阶段案例,不是必修路线或通用倍数。
  • references/kernel-decision.md:按模型shape选择候选、专业能力交接与局部/整模验收。经验演化型:一般性能方法回流本体,专业计量/实现回领域维护源,摘要同步;原始证据留项目。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.