special add in matlab [duplicate]

2019-09-17 10:56发布

问题:

Possible Duplicate:
How to Add a row vector to a column vector like matrix multiplication

I have a nx1 vector and a 1xn vector. I want to add them in a special manner like matrix multiplication in an efficient manner (vectorized):

Example:

A=[1 2 3]'

B=[4 5 6]

A \odd_add B = 
[1+4 1+5 1+6
 2+4 2+5 2+6
 3+4 3+5 3+6
]

I have used bsxfun in MATLAB, but I think it is slow. Please help me...

回答1:

As mentioned by @b3. this would be an appropriate place to use repmat. However in general, and especially if you are dealing with very large matrices, bsxfun normally makes a better substitute. In this case:

>> bsxfun(@plus, [1,2,3]', [4,5,6])

returns the same result, using about a third the memory in the large-matrix limit.

bsxfun basically applies the function in the first argument to every combination of items in the second and third arguments, placing the results in a matrix according to the shape of the input vectors.



回答2:

I present a comparison of the different methods mentioned here. I am using the TIMEIT function to get robust estimates (takes care of warming up the code, average timing on multiple runs, ..):

function testBSXFUN(N)
    %# data
    if nargin < 1
        N = 500;        %# N = 10, 100, 1000, 10000
    end
    A = (1:N)';
    B = (1:N);

    %# functions
    f1 = @() funcRepmat(A,B);
    f2 = @() funcTonyTrick(A,B);
    f3 = @() funcBsxfun(A,B);

    %# timeit
    t(1) = timeit( f1 );
    t(2) = timeit( f2 );
    t(3) = timeit( f3 );

    %# time results
    fprintf('N = %d\n', N);
    fprintf('REPMAT: %f, TONY_TRICK: %f, BSXFUN: %f\n', t);

    %# validation
    v{1} = f1();
    v{2} = f2();
    v{3} = f3();
    assert( isequal(v{:}) )
end

where

function C = funcRepmat(A,B)
    N = numel(A);
    C = repmat(A,1,N) + repmat(B,N,1);
end

function C = funcTonyTrick(A,B)
    N = numel(A);
    C = A(:,ones(N,1)) + B(ones(N,1),:);
end

function C = funcBsxfun(A,B)
    C = bsxfun(@plus, A, B);
end

The timings:

>> for N=[10 100 1000 5000], testBSXFUN(N); end
N = 10
REPMAT: 0.000065, TONY_TRICK: 0.000013, BSXFUN: 0.000031
N = 100
REPMAT: 0.000120, TONY_TRICK: 0.000065, BSXFUN: 0.000085
N = 1000
REPMAT: 0.032988, TONY_TRICK: 0.032947, BSXFUN: 0.010185
N = 5000
REPMAT: 0.810218, TONY_TRICK: 0.824297, BSXFUN: 0.258774

BSXFUN is a clear winner.



回答3:

In matlab vectorization, there is no substitute for Tony's Trick in terms of speed in comparison to repmat or any other built in Matlab function for that matter. I am sure that the following code must be fastest for your purpose.

>> A = [1 2 3]';
>> B = [4 5 6];
>> AB_sum = A(:,ones(3,1)) + B(ones(3,1),:);

The speed differential will be much more apparent (at LEAST an order of magnitude) for larger size of A and B. See this test I conducted some time ago to ascertain the superiority of Tony's Trick over repmatin terms of time consumption.



回答4:

REPMAT is your friend:

>> A = [1 2 3]';
>> B = [4 5 6];
>> AplusB = repmat(A, 1, 3) + repmat(B, 3, 1)

AplusB =

     5     6     7
     6     7     8
     7     8     9