Matlab: Element by element selection without loops - matlab

I have one big matrix of for example 3000X300. And I need to select each element and do several calculations with it. I looked into using the array fun function but because the output of my program is not one value this is not possible.
It works fine now with the loops but it has to preform much faster, so i want to remove the for loop.
Maybe i'll try to be more specific: Each value of the big matrix has to give me an answer of 4 different matrices with the size of 4X6020..
So i don't know if this is possible making this vectorized...
Maybe somebody has other suggestions to make it faster?
greetings,

You can use arrayfun and set uniformoutput to false. See here.

Related

Matlab: need some help for a seemingly simple vectorization of an operation

I would like to optimize this piece of Matlab code but so far I have failed. I have tried different combinations of repmat and sums and cumsums, but all my attempts seem to not give the correct result. I would appreciate some expert guidance on this tough problem.
S=1000; T=10;
X=rand(T,S),
X=sort(X,1,'ascend');
Result=zeros(S,1);
for c=1:T-1
for cc=c+1:T
d=(X(cc,:)-X(c,:))-(cc-c)/T;
Result=Result+abs(d');
end
end
Basically I create 1000 vectors of 10 random numbers, and for each vector I calculate for each pair of values (say the mth and the nth) the difference between them, minus the difference (n-m). I sum over of possible pairs and I return the result for every vector.
I hope this explanation is clear,
Thanks a lot in advance.
It is at least easy to vectorize your inner loop:
Result=zeros(S,1);
for c=1:T-1
d=(X(c+1:T,:)-X(c,:))-((c+1:T)'-c)./T;
Result=Result+sum(abs(d),1)';
end
Here, I'm using the new automatic singleton expansion. If you have an older version of MATLAB you'll need to use bsxfun for two of the subtraction operations. For example, X(c+1:T,:)-X(c,:) is the same as bsxfun(#minus,X(c+1:T,:),X(c,:)).
What is happening in the bit of code is that instead of looping cc=c+1:T, we take all of those indices at once. So I simply replaced cc for c+1:T. d is then a matrix with multiple rows (9 in the first iteration, and one fewer in each subsequent iteration).
Surprisingly, this is slower than the double loop, and similar in speed to Jodag's answer.
Next, we can try to improve indexing. Note that the code above extracts data row-wise from the matrix. MATLAB stores data column-wise. So it's more efficient to extract a column than a row from a matrix. Let's transpose X:
X=X';
Result=zeros(S,1);
for c=1:T-1
d=(X(:,c+1:T)-X(:,c))-((c+1:T)-c)./T;
Result=Result+sum(abs(d),2);
end
This is more than twice as fast as the code that indexes row-wise.
But of course the same trick can be applied to the code in the question, speeding it up by about 50%:
X=X';
Result=zeros(S,1);
for c=1:T-1
for cc=c+1:T
d=(X(:,cc)-X(:,c))-(cc-c)/T;
Result=Result+abs(d);
end
end
My takeaway message from this exercise is that MATLAB's JIT compiler has improved things a lot. Back in the day any sort of loop would halt code to a grind. Today it's not necessarily the worst approach, especially if all you do is use built-in functions.
The nchoosek(v,k) function generates all combinations of the elements in v taken k at a time. We can use this to generate all possible pairs of indicies then use this to vectorize the loops. It appears that in this case the vectorization doesn't actually improve performance (at least on my machine with 2017a). Maybe someone will come up with a more efficient approach.
idx = nchoosek(1:T,2);
d = bsxfun(#minus,(X(idx(:,2),:) - X(idx(:,1),:)), (idx(:,2)-idx(:,1))/T);
Result = sum(abs(d),1)';
Update: here are the results for the running times for the different proposals (10^5 trials):
So it looks like the transformation of the matrix is the most efficient intervention, and my original double-loop implementation is, amazingly, the best compared to the vectorized versions. However, in my hands (2017a) the improvement is only 16.6% compared to the original using the mean (18.2% using the median).
Maybe there is still room for improvement?

Test for Duplicate Quickly in Matlab Array

I have two matrices S and T which have n columns and a row vector v of length n. By my construction, I know that S does not have any duplicates. What I'm looking for is a fast way to find out whether or not the row vector v appears as one of the rows of S. Currently I'm using the test
if min([sum(abs(S - repmat(f,size(S,1),1)),2);sum(abs(T - repmat(v,size(dS_new,1),1)),2)]) ~= 0 ....
When I first wrote it, I had a for loop testing each (I knew this would be slow, I was just making sure the whole thing worked first). I then changed this to defining a matrix diff by the two components above and then summing, but this was slightly slower than the above.
All the stuff I've found online says to use the function unique. However, this is very slow as it orders my matrix after. I don't need this, and it's a massively waste of time (it makes the process really slow). This is a bottleneck in my code -- taking nearly 90% of the run time. If anyone has any advice as how to speed this up, I'd be most appreciative!
I imagine there's a fairly straightforward way, but I'm not that experienced with Matlab (fairly, just not lots). I know how to use basic stuff, but not some of the more specialist functions.
Thanks!
To clarify following Sardar_Usama's comment, I want this to work for a matrix with any number of rows and a single vector. I'd forgotten to mention that the elements are all in the set {0,1,...,q-1}. I don't know whether that helps or not to make it faster!
You may want this:
ismember(v,S,'rows')
and replace arguments S and v to get indices of duplicates
ismember(S,v,'rows')
Or
for test if v is member of S:
any(all(bsxfun(#eq,S,v,2))
this returns logical indices of all duplicates
all(bsxfun(#eq,S,v),2)

Turn a vector's indexes into its content and vice-versa

I'm looking an efficient way to turn the vector:
[1,1,1,2,3,3,3,4,4,4,5,1]
into a vector of vectors such that:
[[1,2,3,12],[4],[5,6,7],[8,9,10],[11]]
In general:
newVector[i] = indexes of the initial vector that contained i
Preferably in Matlab/Octave but I'm just curious if there is an efficient way of achieving this.
I tried looking it up on google and stack but I have no idea what to call this 'operation' so nothing came up.
There is an easy way to do it using accumarray
A = [1,1,1,2,3,3,3,4,4,4,5,1]
accumarray(A',A',[],#(x){find(ismember(A,x))})
But next time, please show your own attempt in your question
Alternatively (but only if A starts from 1 and doesn't skip any numbers)
accumarray(A', (1:size(A,2))', [], #(x){sort(x)})

Matlab GPU use with functions that take arguments of different dimensions

I am trying to use parallel computing with GPU in Matlab, and I would like to apply a function to a large array (to avoid the use of a for loop, which is quite slow). I have read Matlab's documentation, and I can use arrayfun, but only if I want to do elementwise operations. Maybe I am confused, but I would appreciate if someone can help me to use it. As an example of what I want to do, imagine that I would like to perform the following operation,
$X_t = B Z_t + Q\varepsilon_t$
where $X_t$ is 2x1, $B$ is 2x5, and $Z_t$ is 5x1, with $Q$ 2x2. I define a function,
function X = propose(Z,B,Q)
X=Z*B+Q*rand(2,1);
end
Now, suppose that I have an array $Z_p$ which is 5x1000. To each of the 1000 columns I would like to apply the previous function, for given matrices $B$ and $Q$, to get an array $X_p$ which is 2x1000.
Given the documentation for arrayfun I can not do this,
X=arrayfun(#propose,Zp,B,Q)
So, is there any possibility to do it?
Thanks!
PS: Yes, I know that in this simple example I can just do the multiplication without a for loop, but the application I have in mind is more complicated and I cannot do it. I just put this example as an illustration.

How to evaluate matlab fit objects in a cell array without looping?

I have an array of fit objects and I need to evaluate each of them with several values. Because there are over thousand of those fit objects I find it very slow to loop over them and evaluate them with the values. So is there a way to use some kind of vectorized solution to this?
For example I can evaluate a single fit object by
fitArray{1,1}(400)
but what I would like to do is to evaluate multiple fit objects at a time in a way something like this:
fitArray{1:1000}(400)
The looping in Matlab is always very slow and in this case it's really slow as I need to evaluate each of those fits with multiple values.
So is there a way to do that without looping?
Looping is not the biggest problem here, look for example at speed of fitoptions ... the memory allocation is terrible so try to do all operations before the loop itself (fitoptions, fittype etc...). If you use polynomial fitting and you don't need the cfit structure try polyfit instead - should be considerably faster.
I found the answer myself. It was quite simple after all. I achieved the result I wanted by doing this:
vals = repmat({values}, size(fitArray));
evals = cellfun(#feval, fitArray, vals);
This evaluates each fit object in the cell array with the value in the corresponding row in the vals array. So the result is that the evals array has only the results of each fit object.