什么时候不用matlab进行矢量化?

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有一个优秀的逐行分析器,可以帮助您了解矢量化版本的哪些特定部分花费时间.

  • 有时您可以使用**bsxfun**等重写代码以避免缓慢的**repmat**. (4认同)
  • @Jacob:在内存使用方面,作为@thrope siad,`bsxfun`必须为输出分配mem(就像MATLAB中返回结果的任何函数一样).因此,除非您要分配大小接近最大容量的数据(请参阅`memory`函数),否则最好使用`bsxfun`来提高速度.顺便说一句,如果你把'A`缩小一半,我想上面的方法会有效(在我的机器上,我甚至不能首先分配'A`!).但是就CPU时间而言,`bsxfun`更快..看看这个比较:http://blogs.mathworks.com/loren/2008/08/04/comparing-repmat-and-bsxfun-performance/ (2认同)

las*_*ock 9

您是否尝试将执行时间绘制为问题大小的函数(每个向量的元素数量[当前为784],或向量数量[当前为10,000])?当矢量化Gram-Schmidt正交化算法时,我遇到了类似的异常现象; 事实证明,矢量化版本更快,直到问题增长到一定大小,此时迭代版本实际上运行得更快,如下图所示: 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)