Simultaneous sortrows() for all slices of a 3D matrix?

1 view (last 30 days)
I need to apply sortrows to every page of a 3D matrix and I was wondering if there is a faster way of doing this than simply looping through all pages. I have the option to execute on a GPU. While I am aware that sortrows also works with GPU arrays, the code appears to execute much faster on the CPU than on the GPU, probably because of the very long loop.
Here is a minimal working example:
% Parameters:
N = 20;
n = 40;
m = 2;
d = 200000;
% Generate an example matrix 'A':
A = randi(N,n,m,d,'uint16'); % generate a 3D matrix with above parameters
% To be vectorized?
tic;
B = zeros(n,d,'double');
for i=1:d
[~,b] = sortrows(A(:,:,i),[1 2]);
B(:,i) = b;
end
toc;
  3 Comments

Sign in to comment.

Accepted Answer

Bruno Luong
Bruno Luong on 14 Sep 2022
Edited: Bruno Luong on 14 Sep 2022
Code applicable for n == 2 and N < 256 only:
% Parameters:
N = 20;
n = 40;
m = 2;
d = 200000;
% Generate an example matrix 'A':
A = randi(N,n,m,d,'uint16'); % generate a 3D matrix with above parameters
% Original method: To be vectorized?
tic;
B = zeros(n,d,'double');
for i=1:d
[~,b] = sortrows(A(:,:,i),[1 2]);
B(:,i) = b;
end
toc
Elapsed time is 1.019606 seconds.
% Code applicable for n == 2 and N < 256 only
tic
[m,n,p] = size(A);
% Uncomment this sanity test if you are not sure A meets the requirement
% if n ~= 2 && ~all(A<256,'all')
% error('Method 3 not applicable');
% end
C = A(:,1,:)*feval(class(A),2^8) + A(:,2,:);
[~,B3] = sort(C,1);
B3 = reshape(B3,m,d);
toc
Elapsed time is 0.129230 seconds.
isequal(B,B3)
ans = logical
1
  1 Comment
Marin Genov
Marin Genov on 14 Sep 2022
Thanks for posting this method as well! This helps a lot!

Sign in to comment.

More Answers (1)

Bruno Luong
Bruno Luong on 13 Sep 2022
Edited: Bruno Luong on 13 Sep 2022
Somewhat faster
% Parameters:
N = 20;
n = 40;
m = 2;
d = 200000;
% Generate an example matrix 'A':
A = randi(N,n,m,d,'uint16'); % generate a 3D matrix with above parameters
% Original method: To be vectorized?
tic;
B = zeros(n,d,'double');
for i=1:d
[~,b] = sortrows(A(:,:,i),[1 2]);
B(:,i) = b;
end
toc
Elapsed time is 1.090424 seconds.
% No loop but a big permute
tic
[m,n,p] = size(A);
q = repelem((1:p)',m,1);
A3 = reshape(permute(A,[1 3 2]),m*p,n);
A3 = [q,double(A3)];
[~,B2] = sortrows(A3);
B2 = reshape(B2,m,d)-(0:d-1)*m;
toc
Elapsed time is 0.667823 seconds.
isequal(B,B2)
ans = logical
1

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!