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 :
The top left (N-1)x(N-1)
block contains, in each cell, a 6x6
double matrix
The bottom right (N,N)
cell is a MxM
double matrix.
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
)
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!
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}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With