2,002 views (last 30 days)

I would initialize a M x N matrix with the same number. Which could be the best way in terms of speed?

Es.

[2 2;

2 2

2 2]

Matt Fig
on 20 Oct 2012

Another:

% Make a 3-by-8 matrix of 9s:

A(1:3,1:8) = 9

Jan
on 20 Oct 2012

This method can cause problems, if A has been defined before, e.g. by A = rand(9) or A = 'string'.

John BG
on 28 Sep 2016

if it has been defined before ..

if it coincides with the name of a function ..

if you start looking backward there is not way to move forward.

Matt gave the right answer, get on with it, or prove it wrong.

Walter Roberson
on 29 Sep 2016

? You are arguing with a 4 year old posting ?

Jan did give a counter example:

A = rand(9);

A(1:3, 1:8) = 9;

A

A =

9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 0.9651

9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 0.6406

9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 9.0000 0.7577

0.5009 0.5300 0.3514 0.0230 0.6206 0.5925 0.8718 0.5488 0.7359

0.8410 0.9315 0.2206 0.2301 0.4299 0.1449 0.7987 0.3064 0.6590

0.9057 0.9739 0.3609 0.8522 0.6744 0.5350 0.7201 0.2121 0.9933

0.2481 0.8476 0.1054 0.9497 0.9710 0.2542 0.0973 0.6881 0.8679

0.1017 0.7075 0.1900 0.1831 0.3252 0.8435 0.3257 0.7090 0.4237

0.5273 0.9981 0.1697 0.2163 0.9954 0.9812 0.1355 0.4648 0.6465

Part of the array was set as required but the rest was left alone, which does not meet the specifications.

Friedrich
on 14 Aug 2018

Edited: Friedrich
on 15 Aug 2018

I know this is old but I could not let it go. I found

A=zeros(M,N)+10;

to be the fastest. At least on my computer. Heres my code for testing and the results in Matlab 2017b

% produces 6.4GB of data

M = 80e6;

N = 10;

clear A

tic;

A=ones(M,N)*10;

disp(['A=ones(M,N)*10; = ' num2str(toc) 's']);

clear A

tic;

A=uninit(M,N);

A(:) = 10;

disp(['A=uninit(M,N); A(:)=10; = ' num2str(toc) 's']);

clear A

tic;

A=repmat(10,[M,N]);

disp(['A=repmat(10,[M,N]); = ' num2str(toc) 's']);

clear A

tic;

A = mxFastZeros(0,M,N)+10;

disp(['A=mxFastZeros(0,M,N)+10; = ' num2str(toc) 's']);

clear A

tic;

A=zeros(M,N)+10;

disp(['A=zeros(M,N)+10; = ' num2str(toc) 's']);

clear A

tic;

a = 12;

A = a(ones(M, N));

disp(['a=10;A=a(ones(M, N)); = ' num2str(toc) 's']);

clear A

Results

A=ones(M,N)*10; = 3.312s

A=uninit(M,N); A(:)=10; = 2.508s

A=repmat(10,[M,N]); = 2.1169s

A=mxFastZeros(0,M,N)+10; = 1.8326s

A=zeros(M,N)+10; = 1.8487s

a=10;A=a(ones(M, N)); = 25.0576s

Edit: Thank you James for the hint on mxFastZeros. I included that in the benchmark.

Rik
on 18 Jun 2020 at 13:27

I put this in an m-file to be able to run it as a benchmark. There are compilation errors for R2020a (and Octave), so the two R2011a mex files were used for all releases.

I added a normalized time to get values that should not depend too much on my system.

Edit:

Added repelem, randi, and ML6.5, and moved to an answer.

Rik
on 18 Jun 2020 at 15:51

I also added your suggestion with randi and reposted it as an answer to avoid this being burried.

Rik
on 18 Jun 2020 at 15:50

Edited: Rik
on 19 Jun 2020 at 7:42

Inspired by the comparative speed test in the answer by Friedrich, I extended his code to have more robust testing that could be performed on multiple different releases. Timings below are normalized to 10*ones(M,N), and Octave and ML6.5 have fewer elements to prevent max array size errors. See the attached file for all details.

(failed options are removed from this post, but are displayed by the function) (you could make the function more fancy, but I didn't feel like spending time on that. I might update this function at some point)

Matlab 6.5:

A=ones(M,N)*10; = 0.0410s (normalized time = 0.99)

A=zeros(M,N)+10; = 0.0400s (normalized time = 1.01)

A=repmat(10,[M,N]) = 0.0460s (normalized time = 1.14)

a=10;A=a(ones(M, N)); = 0.2770s (normalized time = 6.84)

R2011a:

A=repmat(10,[M,N]) = 1.8918s (normalized time = 0.98)

A=ones(M,N)*10; = 1.8975s (normalized time = 0.99)

A=uninit(M,N); A(:)=10; = 1.9129s (normalized time = 1.00)

A=zeros(M,N)+10; = 2.0259s (normalized time = 1.05)

A=mxFastZeros(0,M,N)+10; = 3.7976s (normalized time = 1.94)

a=10;A=a(ones(M, N)); = 8.4049s (normalized time = 4.36)

A=randi([10,10], M,N); = 12.0829s (normalized time = 6.20)

R2015a:

A=repmat(10,[M,N]) = 0.6856s (normalized time = 0.39)

A=repelem(10, M, N); = 0.7803s (normalized time = 0.44)

A=mxFastZeros(0,M,N)+10; = 1.7123s (normalized time = 0.97)

A=uninit(M,N); A(:)=10; = 1.7477s (normalized time = 0.99)

A=ones(M,N)*10; = 1.7598s (normalized time = 0.99)

A=zeros(M,N)+10; = 1.8429s (normalized time = 1.04)

a=10;A=a(ones(M, N)); = 7.6893s (normalized time = 4.35)

A=randi([10,10], M,N); = 7.7680s (normalized time = 4.40)

R2020a:

A=mxFastZeros(0,M,N)+10; = 0.6672s (normalized time = 0.31)

A=zeros(M,N)+10; = 0.6879s (normalized time = 0.31)

A=repmat(10,[M,N]) = 0.7013s (normalized time = 0.32)

A=repelem(10, M, N); = 0.7761s (normalized time = 0.36)

A=uninit(M,N); A(:)=10; = 1.7886s (normalized time = 0.83)

A=ones(M,N)*10; = 2.1304s (normalized time = 0.98)

A=randi([10,10], M,N); = 6.9900s (normalized time = 3.21)

a=10;A=a(ones(M, N)); = 7.2315s (normalized time = 3.32)

Octave 5.2.0

A=repmat(10,[M,N]) = 0.0264s (normalized time = 0.43)

A=repelem(10, M, N); = 0.0366s (normalized time = 0.59)

A=zeros(M,N)+10; = 0.0583s (normalized time = 0.94)

A=uninit(M,N); A(:)=10; = 0.0628s (normalized time = 1.00)

A=ones(M,N)*10; = 0.0637s (normalized time = 1.03)

a=10;A=a(ones(M, N)); = 0.0945s (normalized time = 1.53)

A=randi([10,10], M,N); = 0.4947s (normalized time = 8.00)

James Tursa
on 18 Jun 2020 at 16:32

What error message did you get when you tried to compile mxFastZeros on R2020a?

Rik
on 18 Jun 2020 at 20:33

This is the output. I replaced the current directory and the install path with placeholders. In case it is relevant: the pwd doesn't have spaces, but the install path does.

Building with 'MinGW64 Compiler (C)'.

Error using mex

{{pwd}}\mxFastZeros.c:14:10: error: conflicting types for 'mxFastZeros'

mxArray *mxFastZeros(mxComplexity ComplexFlag, mwSize m, mwSize n);

^~~~~~~~~~~

In file included from {{mlroot}}/extern/include/mex.h:43:0,

from {{pwd}}\mxFastZeros.c:10:

{{mlroot}}/extern/include/matrix.h:1171:46: note: previous declaration of 'mxFastZeros' was here

LIBMMWMATRIX_PUBLISHED_API_EXTERN_C mxArray *mxFastZeros(int cmplx_flag, int m, int n);

^~~~~~~~~~~

{{pwd}}\mxFastZeros.c:15:10: error: conflicting types for 'mxCreateSharedDataCopy'

mxArray *mxCreateSharedDataCopy(mxArray *mx);

^~~~~~~~~~~~~~~~~~~~~~

In file included from {{mlroot}}/extern/include/mex.h:43:0,

from {{pwd}}\mxFastZeros.c:10:

{{mlroot}}/extern/include/matrix.h:1169:46: note: previous declaration of 'mxCreateSharedDataCopy' was here

LIBMMWMATRIX_PUBLISHED_API_EXTERN_C mxArray *mxCreateSharedDataCopy(const mxArray *pa);

^~~~~~~~~~~~~~~~~~~~~~

James Tursa
on 18 Jun 2020 at 20:44

Looks like they have exposed the true interfaces to these unofficial functions. Just use them. E.g.,

mxArray *mxFastZeros(int cmplx_flag, int m, int n);

mxArray *mxCreateSharedDataCopy(const mxArray *mx);

Jan
on 20 Oct 2012

To avoid troubles with earlier definitions, I prefer:

A = repmat(12, M, N);

The overhead for calling the M-file repmat can be omitted:

a = 12;

A = a(ones(M, N));

James Tursa
on 20 Oct 2012

Edited: James Tursa
on 20 Oct 2012

Another method if matrix A is not already allocated:

A = uninit(M,N);

A(:) = some_number;

UNINIT can be found here:

If the matrix A is pre-existing, then of course skip the allocation step and just fill the values ala the 2nd line above.

SIDE NOTE: On later version of MATLAB it seems the parser is smart enough to recognize the value*ones(m,n) formulation and not actually do the multiply. At least that is my conclusion based on speed tests.

MathWorks Support Team
on 9 Nov 2018

In general, the easiest ways to initialize a matrix with the same number are the following, which produce a 3-by-2 matrix whose elements are all 2:

A = 2*ones(3,2)

A = zeros(3,2) + 2

A = repmat(2,3,2)

The speed of these methods relative to each other can depend on your computing environment.

Matt J
on 11 Nov 2018

Here's a safe one-liner, but I don't know how fast it is.

A=randi([n,n], M,N);

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.