instruction version of colon operator (:)

I have the following situation:
A = sum(sum(o(:,:,n).*o(:,:,m)));
which I would like to vectorize further during the summation.
In GNU Octave there is the vec command which works like
A(:) % = vec(A)
which would allow:
A = sum(vec(o(:,:,n).*o(:,:,m)));
Thus my question is if there is a similar command in Matlab? I know I could use resize or myvec = @(x) x(:) or other more complicated constructs. I am looking for the instruction version of the (:) operator. Alternatively, is there a better way to sum all elements in a matrix?
Thanks ahead!

 Accepted Answer

Cedric
Cedric on 7 Sep 2013
Edited: Cedric on 7 Sep 2013
The way I am managing this is to use RESHAPE, which doesn't realloc or build temp array(s) as far as I could see. So what you do with vec(A) in Octave, should be achievable with reshape(A,1,[]) in MATLAB.
I made the following test on my laptop to check: I setup a watchdog with Process Lasso which kills MATLAB when it uses more RAM than what is available (just so I am not stuck swapping), and built a matrix A a little larger than half the size of the RAM available..
>> A = rand(2e4) ; % 8*(2e4)^2 > half the 5GB avail. on my laptop 8GB.
I then performed the reshape..
>> A = reshape(A, 1, []) ;
which didn't decrease the RAM available, and wasn't killed by Process Lasso. Sometimes we can't see a glitch in RAM usage, which is why I chose to build a case where any realloc or creation of temp array(s) would lead to swapping. Moreover, even without the slow down of swapping, Process Lasso would have caught any glitch in memory usage and killed MATLAB, which didn't happen.
So the following should work:
A = sum( reshape( o(:,:,n).*o(:,:,m), 1, [] )) ;

5 Comments

Mathworks has said specifically that reshape() does not require copying the data portion of an array, just creating a second header.
Did they publish this information specifically for RESHAPE or is there a doc page where they list most frequent operations/functions and specify how many temporary arrays/reallocs/copies are done internally?
To my knowledge, there is no official documentation stating which functions and operations return shared data copies. But RESHAPE has been widely known for years to produce shared data copies for full variables (but not true in general for sparse matrices). The (:) operation is equivalent to RESHAPE in that respect (always produces a shared data copy for full arrays, but not in general for sparse matrices). There are other functions and operations that can produce shared data copies as well, e.g.,
A = X
+X
1*X
X.' (if X is a full real vector)
squeeze(X)
X{etc} (i.e., a cell array element)
X.etc (i.e., a field of a structure)
etc
Also, several functions will return shared data copies if the input is an integer class (e.g., int8, unit16, etc) such as:
ceil, floor, fix, round
There are many other shared data copy examples that I am aware of but I will not list them all here. I will say that in my experience TMW has been pretty good at recognizing when a function or operation does not change data order internally and returning a shared data copy in those circumstances. The main exception to this that I am aware of is the TYPECAST function, which could return a shared data copy but doesn't (although I have a FEX submission that does this).
Thank you. I would like to follow up with the question if reshape is actually what (:) does internally? And if, one preferably would use reshape(A,[],1), because first one actually would expect a column vector, and second advantageous due to the internal matrix representation (column-major)?
Cedric
Cedric on 8 Sep 2013
Edited: Cedric on 8 Sep 2013
I am using both (:) and RESHAPE, the first when I can index the object, and the second when I cannot (which is your case). As you mention, both are useful to ensure that we are dealing with column vectors (without using a lengthy statement if size(x,1)==1, .. else .. end), e.g. in functions when we want to allow users submitting both row and column vectors.
Now they are not equivalent, as (:) is linear indexing and RESHAPE is not (yet it is more versatile). It matters especially from an OOP prospective as (:) can be caught with overloads of indexing methods SUBSREF/SUBSASGN, and RESHAPE should be overloaded on its own.
NOTE: I should have written reshape(A,[],1) in my first answer, as you corrected in your comment.

Sign in to comment.

More Answers (1)

array2D = o(:,:,n) .* o(:,:,m);
% Turn array2D into a vector with (:)
% then you need only one sum().
theSum = sum(array2D(:));

7 Comments

By the way, to get a vector like you did, the equivalent line of code in MATLAB looks like
vec = array2D(:);
Then you could do
theSum = sum(vec);
I do not understand your answer. The whole point of this exercise is to prevent an extra copy into an lvalue of the hadamard products result.
To clarify my question: Is there an instruction(!), NOT the colon operator(!), with the same functionality of (:) allowing the conversion to a vector of a temporary (aka a rvalue in C++ terms) ? (because the chaining of operators like (A.*B)(:) is not allowed in Matlab)
Why do you need to prevent an extra copy / temporary variable?
What you call array2D can be very, very big. As long as it is a rvalue-temporary I suspect the Interpreter/JIT can handle it much more efficiently (scope) than actually having to write to variable (allocate+copy) and then assigning it as another function argument.
I don't think there's a way to vectorize the code and avoid either you explicitly making a temporary variable or MATLAB secretly making an internal copy unbeknownst to you, but I could be wrong. Alternative would be to access elements one at a time via indexing but that would probably be slower especially for your gigantic matrices. By the way, how big are they? How many rows and columns? Thousands, like they're a big high-res image?
The actual size of the matrix only matters in terms of being possibly a significant percentage of the allocatable memory. If I assign a temporary there will be a copy for sure; if on the otherhand I avoid this for example by myvec or reshape or as I was asking a (:)-instruction, it is up to Matlab handling the passing of the result, for which something similar to move-semantics or return-type-optimization might apply due to the tight scoping.
OK, I was just wondering because often we see students, who normally work with arrays with only around 10 columns, refer to a 1000x1000 matrix as "huge", or who have a for loop that takes only a few microseconds spending billions of times that amount of time to vectorize it to save a few nanoseconds - something that will never be noticed. But it sounds like you know what you're talking about and you could be in trouble if your array takes up hundreds of megabytes. Sorry I didn't have good news for you.

Sign in to comment.

Categories

Products

Community Treasure Hunt

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

Start Hunting!