Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go faster than cell2mat

Tags:

cell

matlab

I'm optimizing some code at the moment and can't figure out a way to go faster than MATLAB's cell2mat. For now, the multiple uses of cell2mat in my code represent more than 15% of the processing time.

I think it can go faster than that, because i know the structure of the cell arrays i'll pass to the function.

Basically, the cell array is NxN, where :

  1. The top left (N-1)x(N-1) block contains, in each cell, a 6x6 double matrix

  2. The bottom right (N,N) cell is a MxM double matrix.

  3. The other cells have the right dimensions for concatenating, i.e. :

The cells (1:(N-1),N) are 6xM double matrices, the cells (N,1:(N-1)) are Mx6 double matrices. (Image added for the sake of clarity, there N=207 and M=300)

enter image description here

As the cells will always be filled with doubles AND always be of dimension 2, i'm already only using a small piece of the cell2mat code, i.e. :

 function m = myCell2Mat(c)

    rows = size(c,1);


        m = cell(rows,1);
        % Concatenate one dim first
        for n=1:rows
            m{n} = cat(2,c{n,:});% 73% of the time spent here
        end
        % Now concatenate the single column of cells into a matrix
        m = cat(1,m{:});% 25.2% of the time spent there


  end

This doens't change the time spent much as (like one could imagine), the most time is spent on these lines.

My question is : Does anyone have an idea about how to remove the loop there? I tried something along the lines of :

N=207;
M=300;
C=cell(N,N);
for ii=1:N-1
  for jj=1:N-1
C{ii,jj}=rand(6);
  end
end

for kk=1:(N-1)
C{N,kk}=rand(M,6);
C{kk,N}=rand(6,M);
end

C{end}=rand(M,M);

tmp1=cat(1,C{:,1:(end-1)});
LeftPart=reshape(tmp1,[],6*(size(C,2)-1));

RightPart=cat(1,C{:,end});

Res=[LeftPart RightPart];

But it doesn't show any improvment in time.. (And gives a false result as the reshape operates columnwise)

I've thought about using a recursive function aswell but it doesn't seem to be going anywhere.

Thanks in advance!

like image 763
BillBokeey Avatar asked Nov 03 '15 08:11

BillBokeey


1 Answers

The conclusion from the comments is, that there is no way to improve the performance of cell2mat significantly. Instead I would suggest a better data structure.

You wrote that the data actually represents a 2D-Matrix. Instead of splitting it up into blocks, it's faster to reshape it into a 4D matrix. Let's say your Cell is called C and M is the corresponding 2D matrix

%Old Code
q=C{1,1}
%Faster way to index the same
%1) Convert 2D matrix to 4D
blocksize=6
M=reshape(M,blocksize,size(M,1)/blocksize,blocksize,size(M,2)/blocksize);
%2) Index a block
q=squeeze(M(:,1,:,1))

As reshaping basically takes zero time, you could switch back to the 2D view, for example to process the last row / column. If you want to avoid the conversion back, it is possible to index multiple bocks at once. For the last column use: reshape(M(:,206,:,207:end),6,[]) which corresponds to C{206,207}

like image 143
Daniel Avatar answered Oct 03 '22 08:10

Daniel