Is there a canonical/performant way to reduce arrays/matrices by removing the border values?

Viewed 57

A motivating issue, implemented in Matlab:

N = 1000;
R = zeros(2*N);

for i=0:N-1
    R = R(2:end-1, 2:end-1);
end

For this code timeit() gives a time 2.9793 on my machine. It isn't really great.

By canonical way I mean a discussion that isn't just acceptable, but a performant implementation that respects very large matrices reduced. I would be very appreciative of any answer, referrals to other discussions or literature.

As for language, I am not really a programmer, this question is motivated by a mathematics inquiry and I have encountered performance issues implementing any such reduction process in Matlab. Is there a solution to this in Matlab, or must one delve into the scary depths of C/C++?

One note: One may ask, why not just keep the matrix as is and consider parts of it as needed? To clarify, the reduction process in practice of course depends on the actual (nonzero) values of the elements, e.g. by processing the matrix in 2x2 blocks, and the removal of edge-values is needed to prepare the matrix for then next reduction step.

2 Answers

R(2:end-1, 2:end-1) is the correct way of extracting the part of the array that is all values except the ones at the edges. This requires copying the data, so will take some time. There is no legal way around the copy, and no alternative for extracting a part of the array. (subsref might seems like an alternative, but is the function that is internally called for the given syntax.)

As for illegal ways, you could try James Tursa’s sharedchild from the MATLAB FileExchange. It allows to create an array that references subsets of the data of another array. James is well known in the MATLAB user community as one of the people reverse-engineering the system and bending it to his will. This is solid code. But every version of MATLAB introduces new changes to the infrastructure, so upgrading MATLAB might break your program if you use this code.

You don't need the for loop. If you want to remove L elements from the borders, simply do:

R=R(L+1:end-L, L+1:end-L)

I am surprised you didn't get an error with that code. I think you should end up with an empty matrix at the end of the loop.

Related