Don*_*nie 6 optimization matlab
我正在研究一些处理大型(但不是很大)数据集的matlab代码:10,000个784个元素向量(非稀疏),并计算有关存储在10,000x10稀疏矩阵中的信息.为了使代码工作,我迭代地完成了一些棘手的部分,对10k项进行循环处理,并在稀疏矩阵中的10个项上进行循环以进行清理.
我的过程最初进行了73次迭代(因此,大约730k循环)进行处理,并在大约120秒内运行.不错,但这是matlab,所以我开始对它进行矢量化以加快速度.
最后,我有一个完全矢量化的解决方案得到了相同的答案(所以它是正确的,或者至少和我的初始解决方案一样正确),但是运行需要274秒,它几乎快一半!
这是我第一次遇到matlab代码,它运行速度比迭代运行速度慢.是否有任何经验法则或最佳实践来确定何时可能/可能?
我很乐意分享一些反馈的代码,但这是针对目前开放的学校作业,所以我现在真的不能.如果它最终成为其中之一"哇,这很奇怪,你可能做了一些错误的事情"我可能会在一两周内重新审视这一点,看看我的矢量化是否以某种方式关闭.
rob*_*nce 10
Matlab中的矢量化通常意味着分配更多的内存(制作更大的数组以避免循环,例如通过tony的技巧).在最近版本中改进了循环的JIT编译 - 你的矢量化解决方案所需的内存分配可能意味着没有优势,但是没有看到代码就很难说.Matlab有一个优秀的逐行分析器,可以帮助您了解矢量化版本的哪些特定部分花费时间.
您是否尝试将执行时间绘制为问题大小的函数(每个向量的元素数量[当前为784],或向量数量[当前为10,000])?当矢量化Gram-Schmidt正交化算法时,我遇到了类似的异常现象; 事实证明,矢量化版本更快,直到问题增长到一定大小,此时迭代版本实际上运行得更快,如下图所示:

以下是两个实现和基准测试脚本:
clgs.m
function [Q,R] = clgs(A)
% QR factorization by unvectorized classical Gram-Schmidt orthogonalization
[m,n] = size(A);
R = zeros(n,n); % pre-allocate upper-triangular matrix
% iterate over columns
for j = 1:n
v = A(:,j);
% iterate over remaining columns
for i = 1:j-1
R(i,j) = A(:,i)' * A(:,j);
v = v - R(i,j) * A(:,i);
end
R(j,j) = norm(v);
A(:,j) = v / norm(v); % normalize
end
Q = A;
Run Code Online (Sandbox Code Playgroud)
clgs2.m
function [Q,R] = clgs2(A)
% QR factorization by classical Gram-Schmidt orthogonalization with a
% vectorized inner loop
[m,n] = size(A);
R = zeros(n,n); % pre-allocate upper-triangular matrix
for k=1:n
R(1:k-1,k) = A(:,1:k-1)' * A(:,k);
A(:,k) = A(:,k) - A(:,1:k-1) * R(1:k-1,k);
R(k,k) = norm(A(:,k));
A(:,k) = A(:,k) / R(k,k);
end
Q = A;
Run Code Online (Sandbox Code Playgroud)
benchgs.m
n = [300,350,400,450,500];
clgs_time=zeros(length(n),1);
clgs2_time=clgs_time;
for i = 1:length(n)
A = rand(n(i));
tic;
[Q,R] = clgs(A);
clgs_time(i) = toc;
tic;
[Q,R] = clgs2(A);
clgs2_time(i) = toc;
end
semilogy(n,clgs_time,'b',n,clgs2_time,'r')
xlabel 'n', ylabel 'Time [seconds]'
legend('unvectorized CGS','vectorized CGS')
Run Code Online (Sandbox Code Playgroud)