关于 matlab-optimize-performance
为 MATLAB 用户提供系统化的性能优化工作流,按基准测量、性能分析、优化、复测和正确性验证逐步定位瓶颈。适用于函数、脚本及 GPU 代码的计时与改进。
主要功能
- 01建立运行时间基线
- 02使用 profiler 定位瓶颈
- 03依据分析选择优化模式
- 04复测并计算性能变化
- 05验证优化前后的结果一致性
- 06汇总优化结果
适用场景
- 01查找 MATLAB 函数或脚本的耗时位置
- 02比较代码修改前后的运行时间
- 03评估 GPU 代码的执行性能
- 04优化循环中的数组增长或重复计算
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-optimize-performance安装后在 Claude Code 中输入/matlab-optimize-performance确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
manifest.yamlreferences/measurement-templates.mdoptimization-patterns.md详细介绍
MATLAB 性能优化工作流
用于查找和修复 MATLAB 代码性能瓶颈的系统化 7 步工作流。
适用场景
- 用户要求加快或优化 MATLAB 代码
- 用户想找出 MATLAB 代码运行缓慢的原因
- 用户的函数或脚本运行时间过长
- 用户要求对 MATLAB 代码进行基准测试或计时
- 用户想比较更改前后的性能
- 用户询问 MATLAB 性能最佳实践
不适用场景
- 优化 Simulink 模型仿真速度(使用 Simulink Profiler)
- 瓶颈位于无法在 M 代码层面更改的已编译 C/MEX 代码中
- 性能问题纯粹受 I/O 限制(文件读取、网络、数据库)
- 用户想编写性能测试(使用
writing-matlab-perf-tests技能)
7 步工作流
第 1 步:建立基准
测量当前性能,以便有一个可供改进的数值基准。
针对单个函数:
f = @() targetFunction(input1, input2);
baseline = timeit(f);
fprintf('Baseline: %.4f s\n', baseline);
针对 GPU 代码:
f = @() gpuFunction(gpuInput);
baseline = gputimeit(f);
针对脚本或多步骤工作流:
% Warmup run (first call includes JIT compilation)
myWorkflow(inputs);
% Timed run
tic;
myWorkflow(inputs);
baseline = toc;
fprintf('Baseline: %.4f s\n', baseline);
推荐使用 timeit,因为它会自动预热并运行多个样本。
第 2 步:分析性能
找出实际耗时所在。不要猜测,务必进行性能分析。
profile on;
targetFunction(input1, input2);
profile off;
profile viewer;
查看性能分析器结果:
- 函数摘要——显示每个函数的总耗时和自身耗时。自身耗时是函数本身(不包括其被调用函数)所花费的时间。首先查看自身耗时最高的函数。
- 逐行详情——点击函数名称,查看每一行的耗时。这会揭示确切的瓶颈行。
- 调用次数——被调用数千次或数百万次的函数是优先优化目标。
提示:
- 如果代码运行很快,请在循环中多次运行经过性能分析的代码,以便性能分析器收集足够的样本
- 查看自身耗时,而非总耗时,以找到真正的瓶颈
- 深入分析函数;摘要页面只能呈现部分情况
第 3 步:识别优化机会
根据性能分析结果,判断适用哪些模式。完整列表请参阅 references/optimization-patterns.md。
高影响模式:
| 模式 | 典型加速比 | 查找内容 |
|---|---|---|
| 向量化 | 2–200 倍 | 对数组执行逐元素计算的循环 |
| 预分配 | 2–100 倍 | 在循环中不断扩大的数组(x = [x; newRow]) |
| 避免不必要的重复计算 | 2–50 倍 | 多次计算相同的高开销表达式 |
discretize/histcounts | 2–50 倍 | 对数据进行分箱或分类的循环 |
| 持久缓存 | 1.5–95 倍 | 重复调用 load() 或创建高开销对象 |
| 逻辑索引 | 1.2–5 倍 | 仅为对数组进行索引而使用 find() |
arguments 块 | 1.1–1.8 倍 | 使用 inputParser 的函数 |
| 代数化简 | 1.5–3 倍 | 多余的 sqrt、abs 或矩阵运算 |
优化前,先确认目标是否值得优化:
- 自身耗时是否超过总耗时的 10%?如果没有,优化它的作用不会很大。
- 它是否在紧密循环中调用?高调用次数 × 短耗时 = 高总耗时。
- 它是 M 代码还是内置函数?你无法让内置函数运行得更快,但通常可以减少调用次数(例如,将矩阵传给
filtfilt/filter,而不是循环处理各列)。
第 4 步:实施优化
应用第 3 步中识别的模式。完整模式列表及优化前后代码示例请参阅 references/optimization-patterns.md。
一般原则:
- 从性能分析中影响最大的模式开始
- 将循环中的不变工作移到循环外(对象创建、选项解析、常量表达式)
- 尽可能用数组运算替代逐元素循环
- 使用专用函数(
discretize、cumsum、hypot),而非手写等效实现 - 处理大型数据时,分批进行向量化以控制内存使用(参见目录中的模式 9)
示例——将不变工作移到循环外:
% Before: repeated expensive setup
for i = 1:n
opts = optimoptions('fminunc', 'Display', 'off');
result(i) = fminunc(@(x) cost(x, data(i)), x0, opts);
end
% After: setup once
opts = optimoptions('fminunc', 'Display', 'off');
for i = 1:n
result(i) = fminunc(@(x) cost(x, data(i)), x0, opts);
end
步骤 5:测量优化后的性能
使用与步骤 1 相同的方法重新测量:
f = @() optimizedFunction(input1, input2);
optimized = timeit(f);
speedup = baseline / optimized;
fprintf('Optimized: %.4f s (%.2fx speedup)\n', optimized, speedup);
加速比达到 1.2x 或更高才算显著。低于此值时,测量噪声会让人难以确信这项改动确实带来了提升。
步骤 6:验证正确性
每项优化都必须产生与原始版本相同的结果:
original = originalFunction(input1, input2);
fast = optimizedFunction(input1, input2);
% Numeric comparison (allows floating-point tolerance)
maxErr = max(abs(original(:) - fast(:)));
fprintf('Max error: %.2e\n', maxErr);
assert(maxErr < 1e-10, 'Results differ beyond tolerance!');
对于非数值输出:
assert(isequal(original, fast), 'Results differ!');
如果结果因浮点运算顺序改变(例如,以不同顺序求和)而略有差异,通常可以接受。请记录预期的容差。
步骤 7:报告结果
总结所做的改动及其带来的提升:
fprintf('\n=== Performance Optimization Report ===\n');
fprintf('Target: %s\n', funcName);
fprintf('Baseline: %.4f s\n', baseline);
fprintf('Optimized: %.4f s\n', optimized);
fprintf('Speedup: %.2fx\n', speedup);
fprintf('Correctness: max error = %.2e\n', maxErr);
fprintf('Pattern applied: %s\n', patternName);
进行多项优化时,请分别报告每项优化的加速比,以及端到端的整体提升。
关键规则
- 优化前务必先分析性能——不要猜测瓶颈所在
- 一次只做一项改动——每次优化后都进行测量,以确定哪些改动有效
- 验证正确性——每项优化都必须产生等效输出
- 1.2x 阈值——低于 1.2x 的加速比无法与噪声可靠地区分
- GPU 计时——在 GPU 代码计时前后务必执行
wait(gpuDevice) - 使用
timeit——它会处理预热和平均;基准测试应避免直接使用tic/toc
常见错误
| 错误 | 问题所在 | 正确做法 |
|---|---|---|
| 未进行性能分析就优化 | 你可能会改错地方 | 先分析性能(步骤 2) |
未预热就单次使用 tic/toc | 会计入 JIT 编译时间 | 使用 timeit,或添加一次预热调用 |
| 未同步就测量 GPU 代码 | GPU 操作是异步的;toc 会提前触发 | 前后都执行 wait(gpuDevice) |
| 在循环中扩展数组 | 每次追加都会复制整个数组 | 在循环前预分配 |
| 盲目对超大数组进行向量化 | 可能超出内存限制 | 处理大型数据时使用分块处理 |
| 只报告子函数的加速比 | 如果子函数仅占总耗时的 5%,这样的报告会产生误导 | 务必报告端到端计时结果 |
| 认为速度更快就代表正确 | 错误可能让代码变快(例如跳过了某些工作) | 务必验证结果是否一致(步骤 6) |
参考文件
references/optimization-patterns.md— 优化模式完整目录,包含代码示例和测得的加速比references/measurement-templates.md— 各工作流步骤可直接使用的 MATLAB 脚本模板
版权所有 2026 The MathWorks, Inc.
评论
支持 Markdown