我的问题:我注意到,关于SO的Matlab问题的很多很好的答案经常使用bsxfun函数。为什么?

动机:在Matlab文档bsxfun中,提供了以下示例:

A = magic(5);
A = bsxfun(@minus, A, mean(A))

当然,我们可以使用以下方法执行相同的操作:
A = A - (ones(size(A, 1), 1) * mean(A));

实际上,简单的速度测试表明第二种方法的速度提高了约20%。那么为什么要使用第一种方法呢?我猜在某些情况下,使用bsxfun会比“手动”方法快得多。我真的很想看到这种情况的示例,并解释为什么它更快。

同样,这个问题的最后一个元素,同样来自Matlab文档中的bsxfun:“C = bsxfun(fun,A,B)将由函数handle fun指定的逐元素二进制操作应用于数组A和B,其中单例扩展已启用。”。短语“启用单例扩展已启用”是什么意思?

最佳答案

我使用bsxfun的三个原因(documentationblog link)

  • bsxfunrepmat更快(见下文)
  • bsxfun需要更少的键入
  • 使用bsxfun就像使用accumarray一样,使我对Matlab的理解感到很好。
  • bsxfun将沿输入数组的“单维度”(即数组的大小为1的维度)复制输入数组,以便它们与另一个数组的相应维度的大小匹配。这就是所谓的“单子(monad)展开”。顺便说一句,如果您调用squeeze,则将删除单例尺寸。

    对于很小的问题,repmat方法可能会更快-但在该数组大小下,两个操作都非常快,以至于在整体性能方面不会有任何不同。 bsxfun速度更快有两个重要原因:(1)计算是在编译后的代码中进行的,这意味着数组的实际复制将永远不会发生;(2)bsxfun是多线程Matlab函数之一。

    我在相当快的笔记本电脑上使用R2012b在repmatbsxfun之间进行了速度比较。

    对我来说,bsxfun大约比repmat快3倍。如果数组变大,则差异会更加明显
    repmat运行时的跳转发生在数组大小为1Mb左右,这可能与我的处理器缓存的大小有关-bsxfun的跳转没有那么糟糕,因为它只需要分配输出数组。

    在下面可以找到我用于计时的代码:
    n = 300;
    k=1; %# k=100 for the second graph
    a = ones(10,1);
    rr = zeros(n,1);
    bb=zeros(n,1);
    ntt=100;
    tt=zeros(ntt,1);
    for i=1:n;
       r = rand(1,i*k);
       for it=1:ntt;
          tic,
          x=bsxfun(@plus,a,r);
          tt(it)=toc;
       end;
       bb(i)=median(tt);
       for it=1:ntt;
          tic,
          y=repmat(a,1,i*k)+repmat(r,10,1);
          tt(it)=toc;
       end;
       rr(i)=median(tt);
    end
    

    关于arrays - 在Matlab中,何时最佳使用bsxfun?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12951453/

    10-11 01:53