【问题标题】:Matlab code performance improvementMatlab代码性能提升
【发布时间】:2015-10-24 22:01:49
【问题描述】:

我有一个矩阵 A (MxN),需要使用 A 创建一个矩阵 B (MxNxN),使得 B(:,1,1) = A(:,1)B(:,2,2) = A(:,2)、...、B(:,N,N) = A(:,N)。目前我使用,

B = zeros(size(A,1), size(A,2), size(A,2));
for i=1:size(B,3)
    B(:,i,i) = A(:,i);
end

是否可以使用repmat 或任何其他方法让这段代码比现在运行得更快?

【问题讨论】:

    标签: arrays algorithm performance matlab multidimensional-array


    【解决方案1】:

    可以在B的最后两个维度上使用"partial" linear indexing完成,如下:

    [M, N] = size(A);
    B = zeros(M, N, N);
    B(:, 1:N+1:N^2) = A;
    

    【讨论】:

    • 这个新的索引东西非常有趣,不要以为我曾经尝试过!很酷。
    • @Divakar 谢谢!是的,我也没有多少机会使用它。我什至不知道怎么称呼它,所以我编了一个名字“部分线性索引”。 (Loren Shure 没有给它起名字,她只是说“索引少于维度的索引”)
    • 嗯,我认为这是一个公平的名字,有点介于两者之间!
    【解决方案2】:

    这是一种使用bsxfunshiftdim 的方法:

    m = 3;
    n = 4;
    A = rand(m,n); % example data
    C = bsxfun(@times,A,shiftdim(eye(n),-1));
    

    shiftdim 用于将 N×N 单位矩阵映射到一个 1×N×N 数组,然后乘以 A 并在第一维上虚拟复制。这种方法应该既节省内存又快速。与您的 for 循环版本相比:

    B = zeros(size(A,1), size(A,2), size(A,2));
    for i=1:size(B,3)
        B(:,i,i) = A(:,i);
    end
    

    然后isequal(B,C) 返回1

    【讨论】:

    • 这很好用。我会让你知道大型矩阵的性能改进。谢谢霍克勒
    • 而且对于大输入矩阵来说速度更快。谢谢
    【解决方案3】:

    如果我正确理解您想要做什么,这应该可以解决问题(在我的示例中,您需要将 45 替换为 MN):

    >> A = rand(4, 5) 
    
    A =
    
        0.8147    0.6324    0.9575    0.9572    0.4218
        0.9058    0.0975    0.9649    0.4854    0.9157
        0.1270    0.2785    0.1576    0.8003    0.7922
        0.9134    0.5469    0.9706    0.1419    0.9595
    
    >> B = permute(reshape(repmat(A, 1, 5), 4, 5, 5), [1 3 2]) ;
    >> C = permute(reshape(repmat(eye(5, 5), 1, 4), 5, 5, 4), [3 1 2]) ;
    >> T = C .* B
    >> squeeze(T(1, :, :))
    
    ans =
    
        0.8147         0         0         0         0
             0    0.6324         0         0         0
             0         0    0.9575         0         0
             0         0         0    0.9572         0
             0         0         0         0    0.4218
    

    注意:我没有在 MATLAB 中检查上面的代码,我只使用numpy 进行了检查,但这应该可以满足您的要求。这是python 中使用numpy 的示例:

    >>> import numpy
    >>> import numpy.matlib as matlib
    >>> A = numpy.random.rand(4, 5)
    >>> A
    array([[ 0.44172719,  0.32698936,  0.53422512,  0.39081766,  0.09870158],
           [ 0.65483718,  0.50364349,  0.74913438,  0.87151756,  0.71811372],
           [ 0.54355853,  0.44174294,  0.61738783,  0.74293526,  0.1598779 ],
           [ 0.77675639,  0.204072  ,  0.69584264,  0.04263266,  0.24350847]])
    >>> B = matlib.repmat(A, 1, 5).reshape((4, 5, 5))
    >>> B
    array([[[ 0.44172719,  0.32698936,  0.53422512,  0.39081766,  0.09870158],
            [ 0.44172719,  0.32698936,  0.53422512,  0.39081766,  0.09870158],
            [ 0.44172719,  0.32698936,  0.53422512,  0.39081766,  0.09870158],
            [ 0.44172719,  0.32698936,  0.53422512,  0.39081766,  0.09870158],
            [ 0.44172719,  0.32698936,  0.53422512,  0.39081766,  0.09870158]],
    
           [[ 0.65483718,  0.50364349,  0.74913438,  0.87151756,  0.71811372],
            [ 0.65483718,  0.50364349,  0.74913438,  0.87151756,  0.71811372],
            [ 0.65483718,  0.50364349,  0.74913438,  0.87151756,  0.71811372],
            [ 0.65483718,  0.50364349,  0.74913438,  0.87151756,  0.71811372],
            [ 0.65483718,  0.50364349,  0.74913438,  0.87151756,  0.71811372]],
    
           [[ 0.54355853,  0.44174294,  0.61738783,  0.74293526,  0.1598779 ],
            [ 0.54355853,  0.44174294,  0.61738783,  0.74293526,  0.1598779 ],
            [ 0.54355853,  0.44174294,  0.61738783,  0.74293526,  0.1598779 ],
            [ 0.54355853,  0.44174294,  0.61738783,  0.74293526,  0.1598779 ],
            [ 0.54355853,  0.44174294,  0.61738783,  0.74293526,  0.1598779 ]],
    
           [[ 0.77675639,  0.204072  ,  0.69584264,  0.04263266,  0.24350847],
            [ 0.77675639,  0.204072  ,  0.69584264,  0.04263266,  0.24350847],
            [ 0.77675639,  0.204072  ,  0.69584264,  0.04263266,  0.24350847],
            [ 0.77675639,  0.204072  ,  0.69584264,  0.04263266,  0.24350847],
            [ 0.77675639,  0.204072  ,  0.69584264,  0.04263266,  0.24350847]]])
    >>> C = matlib.repmat(numpy.identity(5), 4, 1).reshape(4, 5, 5) * B
    >>> C
    array([[[ 0.44172719,  0.        ,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.32698936,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.53422512,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.39081766,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.        ,  0.09870158]],
    
           [[ 0.65483718,  0.        ,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.50364349,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.74913438,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.87151756,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.        ,  0.71811372]],
    
           [[ 0.54355853,  0.        ,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.44174294,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.61738783,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.74293526,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.        ,  0.1598779 ]],
    
           [[ 0.77675639,  0.        ,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.204072  ,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.69584264,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.04263266,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.        ,  0.24350847]]])
    

    【讨论】:

    • 我认为这可以产生正确的结果,但是您的 Matlab 代码的输出与 OP 的 B 数组的形式不匹配。
    • @horchler 是的,我正在努力……我用 Python 编写了代码,却忘记了 OP 想要 MATLAB。问题是 python 使用行存储,而 MATLAB 使用列。 ;)
    • @horchler 答案已更新,不太喜欢(比我的 python 脚本丑得多),而且比你的版本慢得多......
    • @Holt。感谢您的努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-11
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    相关资源
    最近更新 更多