最近看到有国外学者总结了提升Matlab程序效率和执行速度的技巧, 原帖是英文撰写的, 我把其搬运成中文, 希望能给大家一些参考。
1. 提前分配内存 memory preallocation
Matlab中存放矩阵时使用连续的内存区域, 当矩阵大小改变时,如果事先未能分配足够的空间,Matlab需要寻找新的足够大的内存区域来复制当前矩阵并存储。 当循环中矩阵大小不断增长时,如果事先未指定矩阵大小, Matlab将不断重复 寻找新空间, 复制矩阵的操作, 会造成很大的延迟。
因此, 在循环之前事先指定矩阵大小是十分重要的加速Matlab程序运行的技巧。 其中zeros()和ones()两个函数式经常使用的初始化矩阵大小的函数。 以下为两个例子:
未事先分配矩阵空间:
tic
for i = 1:30000
A(i) = i;
end
without = toc
事先分配矩阵空间:
tic
B = zeros(30000,1); %Preallocate B with the zeros command.
for i = 1:30000
B(i) = i;
end
with = toc
ratio = without / with
with =
0.0447
ratio =
28.5625
2. 向量化 vectorization
向量化是为适应Matlab平台矢量化计算要求, 而将数据按照矩阵结构进行构造, 使程序执行更加快速, 而摒弃使用循环loop。 向量化操作利用了Matlab中已经封装好了的Lapack和Blas底层线性代数库, 而且支持操作系统多核结构。 具体技巧有:
1). 多利用Matlab自封装向量化函数
Matlab中许多函数支持向量化数据结构, 例如log()函数对一个矩阵A进行操作时, 将分别对A中每个元素element求对数,试着比较如下代码
A = rand(200,200); % We will use this as ourdata
非向量化版本, 利用循环:
tic % time thecode
Bnv = zeros(size(A)); % We preallocate to level theplaying field
for i=1:size(A,1)
forj=1:size(A,2);
Bnv(i,j) = log(A(i,j));
end
end
nonvec = toc;
向量化版本, 直接元素操作:
tic
Bv = log(A);
vec = toc;
assert(isequal(Bnv,Bv));
ratio = nonvec / vec
ratio =
33.0086
更多解释请看:
2).利用逻辑索引(logical indexing)进行矩阵元素操作
利用logical indexing对矩阵内多个元素操作时可以使得代码更加简洁, 运行速度更快。
例如对A矩阵中指定元素进行操作ÿ