diag()的效率 - MATLAB

时间:2015-12-22 15:25:45

标签: performance matlab loops matrix diagonal

动机:

在写出要在数万个矢量上执行的矩阵运算时,我不断遇到警告:

  

请求的200000x200000(298.0GB)阵列超出最大阵列大小   偏爱。创建大于此限制的阵列可能需要很长时间   时间和原因导致MATLAB无法响应。请参阅数组大小限制或   偏好小组了解更多信息。

这样做的原因是我使用diag()来获取矩阵内积的对角线上的值。因为MATLAB通常针对向量/矩阵运算进行了优化,所以当我第一次编写代码时,我通常会使用向量化形式。然而,在这种情况下,MATLAB必须构建整个矩阵,以获得导致内存和速度问题的对角线。

实验:

我决定测试diag()for循环的使用,看看在任何时候使用diag()是否更有效:

num = 200000; % Matrix dimension
x = ones(num, 1);
y = 2 * ones(num, 1);

% z = diag(x*y'); % Expression to solve

% Loop approach
tic
z = zeros(num,1);
for i = 1 : num
   z(i) =  x(i)*y(i);
end
toc

% Dividing the too-large matrix into process-able chunks
fraction = [10, 20, 50, 100, 500, 1000, 5000, 10000, 20000];
time = zeros(size(fraction)); 
for k = 1 : length(fraction)
    f = fraction(k);

    % Operation to time
    tic
    z = zeros(num,1);
    for i = 1 : k
        first = (i-1) * (num / f);
        last = first + (num / f);
        z(first + 1 : last) = diag(x(first + 1: last) * y(first + 1 : last)');
    end
    time(k) = toc;
end

% Plot results
figure;
hold on
plot(log10(fraction), log10(chunkTime));
plot(log10(fraction), repmat(log10(loopTime), 1, length(fraction)));
plot(log10(fraction), log10(chunkTime), 'g*'); % Plot points along time
legend('Partioned Running Time', 'Loop Running Time');
xlabel('Log_{10}(Fractional Size)'), ylabel('Log_{10}(Running Time)'), title('Running Time Comparison');

这是测试的结果: enter image description here (注意:红线代表循环时间作为一个阈值 - 并不是说​​总循环时间是恒定的,无论循环次数如何)

从图中可以清楚地看出,将操作分解为大约200x200平方矩阵,使用diag比使用循环执行相同操作更快。

问题:

有人可以解释为什么我看到这些结果吗?另外,我认为通过MATLAB的更优化设计,可以在diag()函数调用中内置处理这些大型矩阵。例如,它可以只执行i = j索引操作。是否有一个特殊的原因可能会让人望而却步呢?

我还没有真正考虑使用分区方法对diag的内存影响,尽管很明显随着分区大小的减少,内存需求也会下降。

1 个答案:

答案 0 :(得分:3)

检测诊断速度与循环的比率。

初​​始化:

n = 10000;
M = randn(n, n);  %create a random matrix.

诊断的测试速度:

tic;
d = diag(M);
toc;

测试循环速度:

tic;
d = zeros(n, 1);
for i=1:n
   d(i) = M(i,i);
end;
toc;

这将测试诊断。你的代码不是对诊断的干净测试......

评论可能存在混淆的地方

Diag仅提取矩阵的对角线。如果xy是向量,并且d = diag(x * y'),则MATLAB首先构造n乘n矩阵x*y'并在其上调用diag。这就是为什么,你得到错误,“不能构造290GB矩阵......”Matlab解释器没有以疯狂的方式优化,实现你只想要对角线并构造一个向量(而不是完整的带x*y'的矩阵, not 发生。

不确定您是否在询问此问题,但计算d = diag(x*y')的最快方法是xy是n个1向量,只需:d = x.*y < / p>