Got Questions? Get Answers.
Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
speeding up assigning values to a matrix

Subject: speeding up assigning values to a matrix

From: Luca

Date: 5 Apr, 2013 13:34:10

Message: 1 of 8

Hello everybody.
I have a code which I found to be very slow, compared to what I expect.
I have two variables: mask (512x512x97 uint8) and maskC (512x512x97x3, uint8)

(actually the values in mask can be only between 0 and 6.)
I would like to give values to maskC according to the values in "mask".
Now I do this:
ts=tic;
maskC = zeros (512,512,97,3,'uint8');
toc(ts);
ts=tic;
maskC(:,:,:,1) = (mask>1 &mask<3)*255;
toc(ts);
ts=tic;
maskC(:,:,:,2) = (mask>3 & mask<5)*255;
toc(ts);
ts=tic;
mask(:,:,:,3) = (mask>4 &mask<7)*255;
toc(ts);

The output is:
0.0003
0.29
0.31
0.29
It takes me 1 second (!!!!) to set the values of maskC in this way. On a top-speed PC.
What am I doing wrong? I would expect there should be some way to do this in less than 10ms! (like the creation of maskC in 0.3 ms!!)
I think I should be use logical indexing. But I don't see how in this case, where I add another dimension.

Subject: speeding up assigning values to a matrix

From: kinor

Date: 5 Apr, 2013 15:17:18

Message: 2 of 8

"Luca " <l.presottoRE@MOVE.campus.unimib.NOTit> wrote in message <kjmjsi$amg$1@newscl01ah.mathworks.com>...
> Hello everybody.
> I have a code which I found to be very slow, compared to what I expect.
> I have two variables: mask (512x512x97 uint8) and maskC (512x512x97x3, uint8)
>
> (actually the values in mask can be only between 0 and 6.)
> I would like to give values to maskC according to the values in "mask".
> Now I do this:
> ts=tic;
> maskC = zeros (512,512,97,3,'uint8');
> toc(ts);
> ts=tic;
> maskC(:,:,:,1) = (mask>1 &mask<3)*255;
> toc(ts);
> ts=tic;
> maskC(:,:,:,2) = (mask>3 & mask<5)*255;
> toc(ts);
> ts=tic;
> mask(:,:,:,3) = (mask>4 &mask<7)*255;
> toc(ts);
>
> The output is:
> 0.0003
> 0.29
> 0.31
> 0.29
> It takes me 1 second (!!!!) to set the values of maskC in this way. On a top-speed PC.
> What am I doing wrong? I would expect there should be some way to do this in less than 10ms! (like the creation of maskC in 0.3 ms!!)
> I think I should be use logical indexing. But I don't see how in this case, where I add another dimension.


Hi Luca,
i guess your mask(:,:,:,3) = (mask>4 &mask<7)*255;
should be maskC(:,:,:,3) = (mask>4 &mask<7)*255; ?

this is faster but slower than your achieved 10 ms, i wonder if you get it that fast.
ts=tic;
maskC(:,:,:,1) = (mask==2);
toc(ts);
ts=tic;
maskC(:,:,:,2) = (mask==4);
toc(ts);
ts=tic;
maskC(:,:,:,3) = (mask==6);
toc(ts);
tic
maskC = maskC*255;
toc

hth
kinor

Subject: speeding up assigning values to a matrix

From: Luca

Date: 5 Apr, 2013 15:32:09

Message: 3 of 8

"kinor" wrote in message <kjmptu$20a$1@newscl01ah.mathworks.com>...

> Hi Luca,
> i guess your mask(:,:,:,3) = (mask>4 &mask<7)*255;
> should be maskC(:,:,:,3) = (mask>4 &mask<7)*255; ?

Yes, of course!


I'm going to try how faster your version is.
I would not expect reducing the number of scalar multiplications to provide great improvements.
You don't see either a way to use logical indexing, do you?

Subject: speeding up assigning values to a matrix

From: kinor

Date: 5 Apr, 2013 16:06:06

Message: 4 of 8

"Luca " <l.presottoRE@MOVE.campus.unimib.NOTit> wrote in message <kjmqpp$4r7$1@newscl01ah.mathworks.com>...
> "kinor" wrote in message <kjmptu$20a$1@newscl01ah.mathworks.com>...
>
> > Hi Luca,
> > i guess your mask(:,:,:,3) = (mask>4 &mask<7)*255;
> > should be maskC(:,:,:,3) = (mask>4 &mask<7)*255; ?
>
> Yes, of course!
>
>
> I'm going to try how faster your version is.
> I would not expect reducing the number of scalar multiplications to provide great improvements.
> You don't see either a way to use logical indexing, do you?

there is a way which is slower than

ts=tic;
maskC(:,:,:,1) = (mask==uint8(2));
% toc(ts);
% ts=tic;
maskC(:,:,:,2) = (mask==uint8(4));
% toc(ts);
% ts=tic;
maskC(:,:,:,3) = (mask==uint8(6));
% toc(ts);
% tic
maskC = maskC*255;
toc(ts)

still wonder how much time is needed on your system...

Subject: speeding up assigning values to a matrix

From: Luca

Date: 5 Apr, 2013 16:32:25

Message: 5 of 8

I do not understand what you are saying.
What does it mean "there is a way which is slower than" ? Is it a question for me to find a slower way?
Now...
I tried a lot of different operations and I discovered that it is extremely slow to do
A=(mask==num)*255; (1)
(casting or not num to uint8 changes less than 0.1%)

I found it insted to be very fast, acceptably for my scope, to do
A= uint8(mask==num)*uint8(255); (2)

the difference between the (1) and (2) is 300ms for the first one and 15ms for the second one!!!
A factor 20.
Very curious indeed.

That works for now.
(still wondering wether I can use logical indexing to do something like:
aa = (mask==num);
maskC(aa,1)= 250;
and get the best performances of "vectorialized" matlab)

Subject: speeding up assigning values to a matrix

From: dpb

Date: 5 Apr, 2013 19:23:16

Message: 6 of 8

On 4/5/2013 11:32 AM, Luca wrote:
...

> Now... I tried a lot of different operations and I discovered that it is
> extremely slow to do
> A=(mask==num)*255; (1)
> (casting or not num to uint8 changes less than 0.1%)
>
> I found it insted to be very fast, acceptably for my scope, to do
> A= uint8(mask==num)*uint8(255); (2)
>
> the difference between the (1) and (2) is 300ms for the first one and
> 15ms for the second one!!!
> A factor 20.
> Very curious indeed.
>
I see you have found what I was going to suggest; namely that doing
computations in non-natural word lengths can be very time-consuming
owing to the behind-the-scenes casts and addressing problems of not
pulling out and working on full words.

I'd expect if you did the operation entirely on doubles and only cast
the result for it to be slightly better.

> (still wondering wether I can use logical indexing to do something like:
> aa = (mask==num);
> maskC(aa,1)= 250;
> and get the best performances of "vectorialized" matlab)

No. There's a mismatch in dimensions of the logical addressing array
and the target that ML doesn't handle. It seems like it should be
possible to do so, but the syntax isn't implemented.

What happens is shown by the following much smaller example of your case...

 >> m=randi(7,5,5,2)-1;
 >> ix=m==3
ix(:,:,1) =
      0 1 0 0 0
      0 0 0 1 0
      0 0 1 0 0
      0 0 0 0 0
      0 0 0 0 0
ix(:,:,2) =
      0 0 0 0 0
      0 0 0 0 1
      0 0 0 1 1
      0 1 0 0 0
      1 0 1 0 0
 >> M(ix)
ans =
      0
      0
      0
      0
      0
      0
      0
      0
      0
 >>

As you see, when you try to index into M w/ ix, the logical T elements
are returned as a vector. The syntax of keeping ix as the two planes
and then adding another dimension just doesn't work--ML doesn't know how
to do that.

Your only way would be to turn the indices locations in ix above into
the linear addresses in the 4D array based on the sizes and the
column-major storage order expression.

--

Subject: speeding up assigning values to a matrix

From: Luca

Date: 5 Apr, 2013 19:24:17

Message: 7 of 8

I think I've come to the ultimate optimization.
(now I'm at home with a 5 years old laptop, so the performance are way slower than on the verrifast office PC).
This time the quoted times are on this laptop, so definitely longer
I do this:
ts=tic;
maskR= zeros(size(mask),'uint8'); %create 3 RGB separate masks of uint8, same size of the original
maskB=maskR;
maskG=maskR;
toc(ts); %less than 1 ms
ts=tic();
maskR(mask==1)=255;
toc(ts); %180ms
maskG(mask==1|mask==2) = 255;
maskB(mask==2|mask==3) = 255;
%180ms each
ts=tic;
maskC = cat(4,maskR,maskG,maskB);
toc(ts); %140 ms

instead doing;
maskC = zeros (512,512,87,3,'uint8');
maskC(:,:,:,1)= uint8((mask==1))*255;
takes 800ms, 4 times more for each "color". And this is the second best optimization.

The original code
maskC(:,:,:,1) = (mask==1)*255,
takes, on this pc, 1.2 s.
Therefore I've sped up by a factor 10!
I don't think I can get any better. Anyway I think the problem in this "long" execution times are in the fact that I'm dealing with a 76MB matrix...

Subject: speeding up assigning values to a matrix

From: kinor

Date: 8 Apr, 2013 07:52:09

Message: 8 of 8

"Luca " <l.presottoRE@MOVE.campus.unimib.NOTit> wrote in message <kjmuap$gaq$1@newscl01ah.mathworks.com>...
> I do not understand what you are saying.
> What does it mean "there is a way which is slower than" ? Is it a question for me to find a slower way?
> Now...
> I tried a lot of different operations and I discovered that it is extremely slow to do
> A=(mask==num)*255; (1)
> (casting or not num to uint8 changes less than 0.1%)
>
> I found it insted to be very fast, acceptably for my scope, to do
> A= uint8(mask==num)*uint8(255); (2)
>
> the difference between the (1) and (2) is 300ms for the first one and 15ms for the second one!!!
> A factor 20.
> Very curious indeed.
>
> That works for now.
> (still wondering wether I can use logical indexing to do something like:
> aa = (mask==num);
> maskC(aa,1)= 250;
> and get the best performances of "vectorialized" matlab)

Hi Luca

i wanted to say there is a way of logical indexing which is not faster lately this version was slightly faster than all others i tested:

tic
t = uint8(cat(4,(mask==uint8(2)),(mask==uint8(4)),(mask==uint8(6)))) * uint8(255);
toc

best
kinor

Tags for this Thread

No tags are associated with this thread.

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us