概述
最近学习matlab分析和处理几个数据(文件约几百M到一两个G字节),一开始觉得程序很简单,随便写了下,结果matlab处理时间长得让人想哭,边学习边优化,发现主要是for循环占用太长时间,总结下可以去掉for循环的几种情况。
1.用克隆运算符(:和end)
比如一个长向量,想分别改变奇数位置和偶数位置元素的值,这个很简单
a=rand(100);
a(1:2:end)=0;
a(2:2:end)=1;
2.用find或者逻辑索引
比如将矩阵中大于等于128的数减去256(8位补码转为有符号数)
A=randi(256,1,100);A=A-1;
A(A>=128)=A(A>=128)-256;
或者复杂一点,A是一个10*20*30的三维矩阵,B是一个20*30的二维矩阵,如果A(i,j,k)满足某一条件,则用用B(j,k)替代。此处使用到了matlab矩阵的三种索引:下标索引,线性索引,逻辑索引。其中能用逻辑索引就用逻辑索引。
A=zeros(10,20,30);
A(5,6,4)=15;
B=ones(20,30);
[~,c,p]=ind2sub(size(A),find(A==15));
A(A==15)=B(sub2ind(size(B),c,p));
A(5.6,4)
3.用meshgrid等函数
对于一些二维的变换(多变量函数),使用meshigrid,比用两重for循环快多了
tic
[II,JJ]=meshgrid(1:1000,1:1000);
Y=sin(sqrt(II+JJ));
toc
4.使用mat2cell将矩阵转为cell(重点),并使用cellfun对每个小矩阵进行操作,最后用cell2mat转为矩阵
比如一个100*100的二维矩阵,将其分成100个10*10的小矩阵,对每一个小矩阵求均值
A=randi(255,100,100);
A_cell=mat2cell(A,10*ones(1,10),10*ones(1,10));
A_mean=cellfun(@(x)(mean(mean(x))+1),A_cell,'uniformoutput',false); %每一个小块求均值并加1
如果uniformoutput位false,A_mean依然位cell,然后就是一个矩阵
当然,此处完全可以自定义一个函数并存为func.m,然后再cellfun中引用。
%func.m定义函数
func.m
function out=func(in1,in2);
out=in1-in2;
end
%调用func
A=randi(255,100,100);
B=cell(100,100);
A_cell=mat2cell(A,10*ones(1,10),10*ones(1,10));
A_cell=cellfun(@func,A_cell,B_cell,'uniformoutput',false);
两外,为了提高性能,推荐减小新变量,使用in-place操作,比如
使用x=x-1,不要使用y=x-1,
5.掌握改变矩阵结构的函数,比如reshape,permute,squeeze,rot90,shiftdim
有些时候,我们使用循环,是因为矩阵‘不顺’,把矩阵结构改一下,矩阵‘顺了’,自然可以使用简单的方法进行向量化操作。改变结构的时候,要注意matlab的列向量存储的特点。
另外为了提高性能,还要注意内存预分配,这个通过运行matlab的profiler即可,或者写程序的时候注意一下报警(代码下面打波浪线的地方)。profiler配合tic,toc,能很快定位问题,剩下的就是解决问题了。profiler用法如下
profile on;
待执行代码
profile viewer
p = profile('info');
profsave(p,'profile_results') % 保存profile 结果
profile off;
tic toc用法如下:
tic
待执行代码
toc
经过优化代码(向量化操作),即使不借助并行技术(parfor等)或者诸如mex文件等,也能取得满意的效果。当然,如果对时间很敏感,可能还是c或者fortran合适。
最后
以上就是傻傻仙人掌为你收集整理的matlab去掉for循环方法的全部内容,希望文章能够帮你解决matlab去掉for循环方法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复