help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fastest way to element-by-element multiply matix by vector?


From: Michael Creel
Subject: Re: fastest way to element-by-element multiply matix by vector?
Date: Wed, 20 Jun 2007 09:41:16 +0200
User-agent: Thunderbird 1.5.0.12 (X11/20070604)

David Bateman wrote:
Ozzy Lash wrote:
On 6/19/07, Michael Creel <address@hidden> wrote:
Hello all,
I need to element-by-element multiply an nXk matrix A by an nX1 vector b, so
that the result is that each row of A is multiplied by the corresponding row of
b. This is on the inside loop of some intense calculations, so I'd like the best
performance. Is C = A .* repmat(b,1,k) the best way to do this?
Thanks, Michael
The only other way I can think of is:

C = diag(b) * A

Not sure which would be faster, replication and element by element
multiply or diagonalization and matrix multiply.

Better would be

C = spdiags(b,0,n,n) * A

as it doesn't allocate the additional memory of repmat and is as fast as
repmat.. You might also write that as

C = diag(sparse(b)) * A

which is about as  fast or alternatively

C = spdiag(b) * A;

though that is Octave specific and no guarantees that syntax would be
kept. Try the attached script, which runs in both Octave and Matlab..

D.



------------------------------------------------------------------------

1;
clear all;
N = [100,200,500,1000,2000];
K = [100,200,500,1000,2000];
tr = [];
td = [];
ts = [];

for n = N
  for k = K
    fprintf('A(%d,%d)\n', n, k);
    if exist ('OCTAVE_VERSION')
      eval('fflush(stdout);');
    end
    A = randn(n,k);
    b = randn(n,1);

    t0 = cputime();
    C = A .* repmat(b,1,k);
    tr(end+1) = cputime() - t0;

    t0 = cputime();
    C = diag(b) * A;
    td(end+1) = cputime() - t0;

    t0 = cputime();
    %% C = spdiags(b,0,n,n) * A;
    %% C = spdiag(b) * A;
    C = diag(sparse(b)) * A;
    ts(end+1) = cputime() - t0;
  end
end

fprintf('\n\n');
fprintf('(   n,   k)     A.*repmat(b,1,k)     diag(b)*A      spdiag(b)*A\n');
i = 1;
for n = N
  for k = K
    fprintf(  '(%4d,%4d)     %10.4f s     %10.4f s     %10.4f s\n', n, k, ...
           tr(i), td(i), ts(i));
    i = i + 1;
  end
end


Thanks for the script! The results (second run), with Octave 2.9.12 on AMD 64 X2 CPU @2000MHz running 64 bit Kubuntu 7.04 are:
(   n,   k)     A.*repmat(b,1,k)     diag(b)*A      spdiag(b)*A
( 100, 100)         0.0180 s         0.0010 s         0.0060 s
( 100, 200)         0.0010 s         0.0020 s         0.0010 s
( 100, 500)         0.0030 s         0.0040 s         0.0020 s
( 100,1000)         0.0030 s         0.0080 s         0.0040 s
( 100,2000)         0.0060 s         0.0150 s         0.0080 s
( 200, 100)         0.0010 s         0.0040 s         0.0010 s
( 200, 200)         0.0020 s         0.0060 s         0.0020 s
( 200, 500)         0.0030 s         0.0140 s         0.0040 s
( 200,1000)         0.0060 s         0.0260 s         0.0070 s
( 200,2000)         0.0120 s         0.0520 s         0.0150 s
( 500, 100)         0.0010 s         0.0200 s         0.0020 s
( 500, 200)         0.0030 s         0.0360 s         0.0040 s
( 500, 500)         0.0070 s         0.0830 s         0.0110 s
( 500,1000)         0.0140 s         0.1620 s         0.0190 s
( 500,2000)         0.0290 s         0.3160 s         0.0410 s
(1000, 100)         0.0030 s         0.0760 s         0.0030 s
(1000, 200)         0.0060 s         0.1350 s         0.0080 s
(1000, 500)         0.0130 s         0.3150 s         0.0180 s
(1000,1000)         0.0240 s         0.6129 s         0.0370 s
(1000,2000)         0.0570 s         1.1948 s         0.0820 s
(2000, 100)         0.0060 s         0.3080 s         0.0090 s
(2000, 200)         0.0120 s         0.5599 s         0.0160 s
(2000, 500)         0.0240 s         1.2648 s         0.0370 s
(2000,1000)         0.0460 s         2.4296 s         0.0750 s
(2000,2000)         0.1090 s         4.8293 s         0.1670 s
octave:3>

To my taste, the first option wins, though the third is competitive. Thanks again, M.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]