Performance 在Matlab中求矩阵的对角

Performance 在Matlab中求矩阵的对角,performance,matlab,matrix,diagonal,Performance,Matlab,Matrix,Diagonal,设A为大小为[n,n]的矩阵。如果我想提取它的对角线,我会diag(A) 实际上,我想要相反的对角线,它是[A(n,1),A(n-1,2),A(n-2,3),…] 一种方法是通过diag(flipud(A))。但是,flipud(A)非常浪费,与通常的对角线相比,它所花费的时间增加了10倍 我正在寻找一种快速获得相反对角线的方法。自然地,for循环似乎非常慢。非常感谢您的建议。您想要的元素很容易通过索引获得。例如,这应该可以做到 n = 4; A = magic(n) A = 16

A
为大小为
[n,n]
的矩阵。如果我想提取它的对角线,我会
diag(A)

实际上,我想要相反的对角线,它是
[A(n,1),A(n-1,2),A(n-2,3),…]

一种方法是通过
diag(flipud(A))
。但是,
flipud(A)
非常浪费,与通常的对角线相比,它所花费的时间增加了10倍


我正在寻找一种快速获得相反对角线的方法。自然地,
for
循环似乎非常慢。非常感谢您的建议。

您想要的元素很容易通过索引获得。例如,这应该可以做到

n = 4;
A = magic(n)
A =
    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1

A(cumsum(n + [0,repmat(-1,1,n-1)]))
ans =
     4     7    10    13

我也可以使用sub2ind来获取这些元素索引,但这样做更简洁,尽管它的工作原理不太明显。

这是我的矩阵,由a=magic(5)生成


下面是迄今为止提到的所有方法的比较,以及我能想到的一些其他变化。这是在64位R2013a上使用函数进行测试的

function [t,v] = testAntiDiag()
    % data and functions
    A = magic(5000);
    f = {
        @() func0(A) ;
        @() func1(A) ;
        @() func2(A) ;
        @() func3(A) ;
        @() func4(A) ;
        @() func5(A) ;
        @() func6(A) ;
        @() func7(A) ;
    };

    % timeit and check results
    t = cellfun(@timeit, f, 'UniformOutput',true);
    v = cellfun(@feval, f, 'UniformOutput',false);
    assert( isequal(v{:}) )
end


function d = func0(A)
    d = diag(A(end:-1:1,:));
end

function d = func1(A)
    d = diag(flipud(A));
end

function d = func2(A)
    d = flipud(diag(fliplr(A)));
end

function d = func3(A)
    d = diag(rot90(A,3));
end

function d = func4(A)
    n = size(A,1);
    d = A(n:n-1:end-1).';
end

function d = func5(A)
    n = size(A,1);
    d = A(cumsum(n + [0,repmat(-1,1,n-1)])).';
end

function d = func6(A)
    n = size(A,1);
    d = A(sub2ind([n n], n:-1:1, 1:n)).';
end

function d = func7(A)
    n = size(A,1);
    d = zeros(n,1);
    for i=1:n
        d(i) = A(n-i+1,i);
    end
end
计时(与上面定义的顺序相同):

最让我吃惊的结果是最后一个。显然,JIT编译在这种简单的for循环上非常有效

A=魔术(6)

A=

b=diag(A(1:长度(A),长度(A):-1:1))

b=


我更新了结果(我没有把笔记本电脑插上电源,所以CPU节流使它变慢了!)。我的结论是它们非常相似,也许你错了:)谢谢你的比较和Knuth的建议!稍微快一点的版本:
A(sqrt(end):sqrt(end)-1:end-1)
可能与FYI重复,正确的术语是“”。
function [t,v] = testAntiDiag()
    % data and functions
    A = magic(5000);
    f = {
        @() func0(A) ;
        @() func1(A) ;
        @() func2(A) ;
        @() func3(A) ;
        @() func4(A) ;
        @() func5(A) ;
        @() func6(A) ;
        @() func7(A) ;
    };

    % timeit and check results
    t = cellfun(@timeit, f, 'UniformOutput',true);
    v = cellfun(@feval, f, 'UniformOutput',false);
    assert( isequal(v{:}) )
end


function d = func0(A)
    d = diag(A(end:-1:1,:));
end

function d = func1(A)
    d = diag(flipud(A));
end

function d = func2(A)
    d = flipud(diag(fliplr(A)));
end

function d = func3(A)
    d = diag(rot90(A,3));
end

function d = func4(A)
    n = size(A,1);
    d = A(n:n-1:end-1).';
end

function d = func5(A)
    n = size(A,1);
    d = A(cumsum(n + [0,repmat(-1,1,n-1)])).';
end

function d = func6(A)
    n = size(A,1);
    d = A(sub2ind([n n], n:-1:1, 1:n)).';
end

function d = func7(A)
    n = size(A,1);
    d = zeros(n,1);
    for i=1:n
        d(i) = A(n-i+1,i);
    end
end
>> testAntiDiag
ans =
   0.078635867152801
   0.077895631970976    % @AlexR.
   0.080368641824528
   0.195832501156751
   0.000074983294297    % @thefourtheye
   0.000143019460665    % @woodchips
   0.000174679680437
   0.000152488508547    % for-loop
35     1     6    26    19    24
 3    32     7    21    23    25
31     9     2    22    27    20
 8    28    33    17    10    15
30     5    34    12    14    16
 4    36    29    13    18    11
24
23
22
33
 5
 4