What are efficient ways to extract lower dimensional slices from a high-dimensional array ?

조회 수: 6 (최근 30일)
I am looking for an efficient way to extract sub-arrays from a larger array. There are (at least) two standard solutions both having certain disadvantages.
First solution: Use a loop Disadvantage: Might be slow if nidx (see code below) is large
Second solution: use sub2ind Disadvantage: Interim indices created are large if nidx * ndim3 is large
Any other (especially better) ideas?
Kind regards, gg
%create 3dim testarray
ndim1 = 3;
ndim2 = 4;
ndim3 = 5;
testarr = rand([ndim1,ndim2,ndim3]);
%pick some indices into the first two dimensions
nidx = 10;
idx1 = randi([1,ndim1],[nidx,1]);
idx2 = randi([1,ndim2],[nidx,1]);
%now extract slices from testarr according to the indices
%First solution: by loop
newarr = zeros(nidx, ndim3);
for kidx = 1:nidx
newarr(kidx,:) = testarr(idx1(kidx), idx2(kidx), :);
end
%Second solution using sub2ind
refidx1 = repmat(idx1, [ndim3,1]);
refidx2 = repmat(idx2, [ndim3,1]);
tmp = repmat((1:ndim3),[nidx, 1]);
refidx3 = tmp(:);
lidx = sub2ind(size(testarr), refidx1, refidx2, refidx3);
newarr_alt = reshape(testarr(lidx), nidx, ndim3);
%are they equal this time?
isequal(newarr, newarr_alt)
  댓글 수: 4
James Tursa
James Tursa 2011년 12월 14일
Copying the data can easily dominate the run time over the calculations involved, particularly for something as simple as squaring elements or setting elements to a value. E.g., a mex routine can often significantly outperform m-code for these cases.
gg
gg 2011년 12월 16일
Now I understand! Yes, of course you are completely right. But then on a MEX level this problem doesn't arise. Andrei's way of doing index arithmetic is the way to do it in C, isn't it?
So I was really asking (not entirely precise obviously) on a MATLAB intrinsic way of doing it, without using MEX.
Note that if you are using Andrei's method you create an index (somewhat implicitely though). So even if you do in situ calculations you may need to allocate memory for this index. Actually it is not clear to me under what conditions, which solution is the "best". Except for MEX maybe which seems to be straightforward and thus quick. I have never used it but then there might be overheads involved as well?

댓글을 달려면 로그인하십시오.

채택된 답변

Andrei Bobrov
Andrei Bobrov 2011년 12월 14일
s = size(testarr);
m = prod(s(1:2));
out = testarr(bsxfun(@plus,idx2*(s(1)-1)+idx1,0:m:(s(3)-1)*m))
  댓글 수: 1
gg
gg 2011년 12월 14일
Andrei,
Thanks!
I consider this an optimissed variant of sub2ind. It does suffer from creating an auxiliary index as well. Although the size is only ndim3 as opposed to ndim3 * nidx, which is certainly a huge improvement. It will be interesting to compare speed.

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Resizing and Reshaping Matrices에 대해 자세히 알아보기

제품

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by