Efficiently Swapping Columns in a Matrix
20 views (last 30 days)
Show older comments
Kyle Marocchini
on 23 Jun 2016
Commented: Kyle Marocchini
on 30 Jun 2016
Is there a more efficient/faster way to switch out two columns in a matrix than calling:
A(:,[i j]) = A(:,[j i]);
If anyone knew of faster implementation (possibly even using MEX), I would greatly appreciate them sharing.
3 Comments
James Tursa
on 23 Jun 2016
Edited: James Tursa
on 23 Jun 2016
This could easily be done in a mex routine in-place (I can post the code if you want). I don't know how much faster it would run. The caveat is that if A is shared with another variable then you would have unwanted side effects. Do you know if A is shared with any other variable?
Accepted Answer
James Tursa
on 24 Jun 2016
Edited: James Tursa
on 28 Jun 2016
Here is the mex code to swap columns in-place. Note that it is up to the user to make sure the input matrix is not shared with another variable, since every shared variable would have their columns swapped in that case.
/* swapcolumns.c Swaps columns of X in-place.
* Relies on user to make sure X is not shared with another variable
* since there is no checking for this in the code.
* Syntax: swapcolumns(X,i,j)
* X = a matrix (any standard class ... no objects)
* i,j = columns to swap
* Programmer: James Tursa
* Date: June 24, 2016
*/
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
unsigned char b;
unsigned char *data, *target, *source;
size_t M, N, i, j, k, c, bytes;
if( nrhs == 0 ) {
mexPrintf("swapcolumns -> Swaps columns of X in-place.\n");
mexPrintf("Relies on user to make sure X is not shared with another variable\n");
mexPrintf("since there is no checking for this in the code.\n");
mexPrintf("Syntax: swapcolumns(X,i,j)\n");
mexPrintf(" X = a matrix (any standard class ... no objects)\n");
mexPrintf(" i,j = columns to swap\n");
return;
}
if( nrhs != 3 ) {
mexErrMsgTxt("Need exactly 3 inputs");
}
if( nlhs > 0 ) {
mexErrMsgTxt("Too many outputs\n");
}
if( !(mxIsNumeric(prhs[0]) || mxIsChar(prhs[0]) || mxIsLogical(prhs[0]) ||
mxIsCell(prhs[0])) ) {
mexErrMsgTxt("1st argument needs to be standard class");
}
M = mxGetM(prhs[0]);
N = mxGetN(prhs[0]);
if( M == 0 || N == 0 ) {
return;
}
i = (size_t) mxGetScalar(prhs[1]);
j = (size_t) mxGetScalar(prhs[2]);
if( i > N || j > N ) {
mexErrMsgTxt("Column index(es) are too large");
}
if( i == 0 || j == 0 ) {
mexErrMsgTxt("Column index(es) cannot be 0");
}
data = mxGetData(prhs[0]);
bytes = M * mxGetElementSize(prhs[0]);
c = 2;
while( c-- ) {
target = data + (i-1) * bytes;
source = data + (j-1) * bytes;
for( k=0; k<bytes; k++ ) {
b = *target;
*target++ = *source;
*source++ = b;
}
if( mxIsNumeric(prhs[0]) && mxIsComplex(prhs[0]) ) {
data = mxGetImagData(prhs[0]);
} else {
break;
}
}
}
More Answers (3)
the cyclist
on 23 Jun 2016
Are you certain you actually have to "physically" swap the columns every time? Could you instead simply keep track of the swaps, and then index into the resulting matrix, or do one massive multi-column swap at the end? Just a thought.
2 Comments
Philip Borghesani
on 23 Jun 2016
Edited: Philip Borghesani
on 23 Jun 2016
Does your data need to be in a matrix? Swaping two elements of a cell array will be much faster for large element sizes and will be similar to an array list or general list.
%swaptime.m
sz=1e8;
m=ones(sz,5);
for col=1:5
c{col}=ones(sz,1);
end
tic
m(:,[2,5])=m(:,[5,2]);
toc
tic
c([2,5])=c([5,2]);
toc
>> swaptime
Elapsed time is 1.295767 seconds.
Elapsed time is 0.000899 seconds.
2 Comments
Roger Stafford
on 25 Jun 2016
It is possible that matlab accomplishes A(:,[i j]) = A(:,[j i]); by the compiler equivalent of
t1 = A(:,i);
t2 = A(:,j);
A(:,i) = t2;
A(:,j) = t1;
which requires 4*n transfers. If you wrote a mex file that does the equivalent of
t = A(:,i);
A(:,i) = A(:,j);
A(:,j) = t;
it would take only 3*n transfers. I cannot think of any more significant gains that you might make on this kind of swapping. Swapping inherently involves a transfer to temporary storage, transfer of another into the previous location, and finally transfer from temporary storage into the second location.
0 Comments
See Also
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!