如果以后有可能在工作和学习中熟练掌握matlab,一定要收藏这篇干到超级无聊的干货。此篇对5级及以下学习者暂时没有学习必要,请尽情忽略。
今天先总结十个优化matlab运行速度的方案,以后慢慢增加内容——
% 对于内存消耗非常大的情况
% 测试不提前分配val的内存
tic,
for i=1:2000
for j=1:2000
val1=rand;
val2=rand;
val(i,j)=val1*val2;
end
end
toc
% 测试提前分配val内存
val=zeros(2000);
tic,
for i=1:2000
for j=1:2000
val1=rand;
val2=rand;
val(i,j)=val1*val2;
end
end
toc
% 如果不能提前确定数据量有多大,可以提前分配一个较大的内存,然后截断
% 常见于从文本中获取数据
% 写for循环之前先看看能否改成矩阵运算
% matlab二维矩阵运算速度非常快,但是三维矩阵运算并不快
A=randi(100,100,1000);
B=randi(100,1000,200);
C=zeros(100,200);
% 测试for循环的速度
tic,
for i=1:100
for j=1:200
C(i,j)=A(i,:)*B(:,j);
end
end
toc
% 测试矩阵运算的速度
tic,
C=A*B;
toc
% 如果有多重循环,parfor放在最外层的循环才能最有效的并行加速
% 注意变量类型,当不能使用parfor运算可能能通过改变变量类型使用。
% 测试非并行程序
tic,
val=zeros(500);
for i=1:500
for j=1:500
val(i,j)=integral(@(x)sin(x),min(i,j),max(i,j));
end
end
toc
% 如果有多重循环,只能在一层加parfor(外层加速效率高),
% 最好调整多层for循环的循环次序,将迭代多的循环放在最外侧。
% 测试并行程序,在外侧并行
tic,
val=zeros(500);
parfor i=1:500 % 注意,启动parfor是需要一点时间的,可以启动后重新运行下测试代码
for j=1:500
val(i,j)=integral(@(x)sin(x),min(i,j),max(i,j));
end
end
toc
% 测试并行程序,在内侧并行
tic,
val=zeros(500);
for i=1:500 % 注意,启动parfor是需要一点时间的,可以启动后重新运行下测试代码
parfor j=1:500
val(i,j)=integral(@(x)sin(x),min(i,j),max(i,j));
end
end
toc
% matlab里面很多函数可以达到同一功能,注意使用最新最快的
% 测试str2double实现字符串到数值的转换
tic,
for i=1:10000
val=str2double('111');
end
toc
% 测试str2num实现字符串到数值的转换
tic,
for i=1:10000
val=str2num('111');
end
toc
% fill画图和pcolor画图
colordata=randi(2,100,100);
% 测试fill画图
tic,
figure
hold on
for i=1:100
for j=1:100
if colordata(i,j)==1
fill([i-1,i,i,i-1],[j-1,j-1,j,j],'y')
else
fill([i-1,i,i,i-1],[j-1,j-1,j,j],'b')
end
end
end
toc
% 测试pcolor画图
tic,
figure
pcolor(colordata)
toc
% 能用逻辑运算就用逻辑运算
% 很多看似不能使用逻辑运算的情形是可以使用逻辑运算的
% 统计data第一列和第二列同时大于0的情况的数量
data=randi(100000,2)-0.5;
% 测试逻辑运算
tic,
sum(data(:,1)>0&data(:,2)>0)
toc
% 测试find
tic,
ind1=find(data(:,1)>0);
ind2=find(data(:,2)>0);
length(intersect(ind1,ind2))
toc
% 对速度要求高时优先使用数值计算,避免符号计算
% 符号运算和数值计算分别算同一个积分(对部分积分,符号运算无法得到结果,只能选择数值计算)
% 计算sin(x)在0到1上的积分(sin(x)可以直接通过原函数计算积分,这里仅为了举例方便)
% 测试符号运算,重复100次,统计耗时
syms x % 这一步耗时不统计在内
tic,
for i=1:100
y=sin(x);
val=double(int(y,x,0,1));
end
toc
% 测试数值积分,重复100次,统计耗时
syms x % 这一步耗时不统计在内
tic,
for i=1:100
y=sin(x);
val=double(int(y,x,0,1));
end
toc
对于部分耗时非常大的代码,可以提前存储运算值。
例如对于上面的积分运算,如果积分重复非常多次,但是积分的上下边界可能范围优先,那么可以提前存储所有可能的边界范围的积分值。
后期单独一篇教程讲解。
% 使用profile监测每行代码运行速度,针对性改进
% 在检测的代码块前后分别加入 profile on, profileviewer即可
profile on
% 测试提前分配val内存
syms x
for i=1:1000
y=sin(x);
val1=int(y,x,0,1);
val2=integral(@(x)sin(x),0,1);
end
profile viewer