性能优化 #

一、性能分析 #

1.1 tic和toc #

matlab
% 计时
tic;
result = my_function();
elapsed = toc;
fprintf('耗时: %.4f 秒\n', elapsed);

1.2 timeit函数 #

matlab
% 更精确的计时
t = timeit(@() my_function(x));
fprintf('平均耗时: %.4f 秒\n', t);

1.3 Profiler #

matlab
% 启动Profiler
profile on;

% 运行代码
my_function();

% 查看结果
profile viewer;
profile off;

% 获取数据
p = profile('info');

二、向量化 #

2.1 避免循环 #

matlab
% 不推荐:循环
n = 1e6;
result = zeros(1, n);
for i = 1:n
    result(i) = sin(i);
end

% 推荐:向量化
result = sin(1:n);

2.2 向量化运算 #

matlab
% 元素运算
A = rand(1000, 1000);
B = rand(1000, 1000);

% 矩阵运算(向量化)
C = A .* B;    % 元素乘法
C = A + B;     % 加法
C = A .^ 2;    % 元素平方

% 避免循环
% 不推荐
for i = 1:size(A, 1)
    for j = 1:size(A, 2)
        C(i, j) = A(i, j) * B(i, j);
    end
end

% 推荐
C = A .* B;

2.3 使用内置函数 #

matlab
% 不推荐:手动实现
function s = my_sum(A)
    s = 0;
    for i = 1:length(A)
        s = s + A(i);
    end
end

% 推荐:使用内置函数
s = sum(A);

三、预分配 #

3.1 数组预分配 #

matlab
% 不推荐:动态扩展
tic;
data = [];
for i = 1:10000
    data = [data, rand()];
end
toc;  % 较慢

% 推荐:预分配
tic;
data = zeros(1, 10000);
for i = 1:10000
    data(i) = rand();
end
toc;  % 较快

3.2 元胞数组预分配 #

matlab
% 预分配元胞数组
data = cell(1, 10000);
for i = 1:10000
    data{i} = rand();
end

3.3 结构体数组预分配 #

matlab
% 预分配结构体数组
data = struct('x', cell(1, 10000), 'y', cell(1, 10000));
for i = 1:10000
    data(i).x = rand();
    data(i).y = rand();
end

四、内存优化 #

4.1 选择合适的数据类型 #

matlab
% 使用合适的数据类型
data_int8 = int8(randi([0 255], 1000, 1000));   % 1 MB
data_double = double(randi([0 255], 1000, 1000)); % 8 MB

% 使用single
data_single = single(rand(1000, 1000));  % 4 MB
data_double = double(rand(1000, 1000));  % 8 MB

4.2 避免不必要的复制 #

matlab
% 不推荐:创建副本
A = rand(10000);
B = A;  % 复制
B(1) = 0;  % 触发写时复制

% 推荐:直接操作
A = rand(10000);
A(1) = 0;

4.3 及时清除变量 #

matlab
% 处理大数据后清除
large_data = rand(10000);
result = sum(large_data(:));
clear large_data;  % 释放内存

五、并行计算 #

5.1 parfor #

matlab
% 普通for循环
tic;
result = zeros(1, 1000);
for i = 1:1000
    result(i) = sum(rand(1000));
end
toc;

% 并行for循环
tic;
result = zeros(1, 1000);
parfor i = 1:1000
    result(i) = sum(rand(1000));
end
toc;

5.2 并行池 #

matlab
% 启动并行池
pool = parpool;

% 关闭并行池
delete(pool);

% 检查并行池状态
pool = gcp('nocreate');
if isempty(pool)
    parpool;
end

5.3 并行计算注意事项 #

matlab
% parfor限制
parfor i = 1:1000
    % 不能使用break、continue
    % 变量分类要明确
    result(i) = compute(i);
end

% 广播变量
param = 0.5;
parfor i = 1:1000
    result(i) = compute(i, param);  % param是广播变量
end

六、其他优化技巧 #

6.1 使用稀疏矩阵 #

matlab
% 稀疏矩阵
A = sparse(10000, 10000);
A(1, 1) = 1;
A(10000, 10000) = 1;

% 转换
A_full = full(A);  % 稀疏转全
A_sparse = sparse(A_full);  % 全转稀疏

6.2 使用MEX文件 #

matlab
% 对于计算密集型任务,可以使用C/C++编写MEX文件
% mex my_function.c

6.3 JIT优化 #

matlab
% MATLAB的JIT编译器会自动优化循环
% 确保循环体简单,避免复杂数据结构

七、性能对比示例 #

7.1 对比测试 #

matlab
function compare_performance()
    n = 1e6;
    
    % 方法1:循环
    tic;
    result1 = zeros(1, n);
    for i = 1:n
        result1(i) = sin(i);
    end
    t1 = toc;
    
    % 方法2:向量化
    tic;
    result2 = sin(1:n);
    t2 = toc;
    
    fprintf('循环: %.4f 秒\n', t1);
    fprintf('向量化: %.4f 秒\n', t2);
    fprintf('加速比: %.2fx\n', t1/t2);
end

八、总结 #

本章学习了:

  1. 性能分析:tic/toc、timeit、Profiler
  2. 向量化:避免循环、使用内置函数
  3. 预分配:数组、元胞、结构体
  4. 内存优化:数据类型、避免复制
  5. 并行计算:parfor、并行池

下一章将学习工具箱的使用。

最后更新:2026-03-27