Using parfor in MATLAB for indirect indexing of an array - matlab

I am currently trying to parallelize my script for runtime benefits.
My code includes a segment, which has the following form when represented in a very abstract way:
x=zeros(5,1);
y{1}=[1; 3; 5];
y{2}=[2; 4];
parfor i=1:2
x(y{i})= func(y{i});
end
So, I want to populate the indices of the variable x not sequentially, but in a parallel way. This gives me, however, the following error:
The variable x in a parfor cannot be classified.
The indices to be assigned are always disjoint (such as the example [1; 3; 5] and [2; 4]) i.e. no overwriting of entries will occur during the parallel run, which would have otherwise jeopardized the non-sequential processing.
Is there perhaps another way to reformulate this functionality?

I would use structs since output size is changing.
x=zeros(5,1);
y{1}=[1; 3; 5];
y{2}=[2; 4];
parfor i=1:2
temp{i}= sin(y{i});
end
for i=1:2
x(y{i})=temp{i};
end

Related

Can we nest many do-until loops together using just one do in octave?

I have several conditions to be satisfied so as the code to run properly. So, can I use many until . For example, I have a code that uses for loop to compute several matrices. But, my further code requires the matrices computed to be seperately invertible.
Code:
n=4;
p=3;
% x1=a[4 x3] vector
%gamma(:,:,i) is some [4x 4] matrix
for i=1:n
do
v_k=blkdiag(eye(n-i),gamma(:,:,i),eye(i-1);
bar_B=v_k(1:p,:);
bar_A=v_k(p+1:n+p,:);
until (det(bar_A)!=0)
x1=inv(eye(n)-bar_A);
until (det((x1*bar_B))!=0)
endfor;
Any ideas. Thanks beforehand.

Parallelize MATLAB for loop to calculate MLE

I am attempting to speed up my MATLAB code by using parfor, however, I am doing it incorrectly. My code is rather simple, I am fitting some data using MATLAB's built-in mle function by using varying initial guesses for the mean (mm) and variance (vv). onestagepdf2 is my probability density function.
Here is the code snippit:
mm=linspace(.1, 1, 2); % mean
vv=linspace(.1, 2, 2); % variance
N=length(mm);
n=length(vv);
pd=zeros(n*N,2);
ld = NaN*ones(n*N,1);
options = statset('MaxIter',10000, 'MaxFunEvals',10000);
parfor i=1:N % pick a mean
m=mm(i);
parfor j=1:n % pick a variance
v=vv(j);
x0=[m,v];
[p,conf1]=mle(data,'pdf',#onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
pd(n*(i-1)+j,:)=p; % store parameter values from mle
l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
ld(n*(i-1)+j)=sum(log(l)); % store likelihood value
end
end
The error that I receive is:
'The variable pd in a parfor cannot be classified.'
pd = zeros(n, N, 2); %initialise culprits
ld= zeros(n,N);
parfor ii=1:N % pick a mean
m=mm(ii);
for jj=1:n % Parallellise the second parfor
v=vv(jj);
x0=[m,v];
[p,conf1]=mle(data,'pdf',#onestagepdf2,'start',x0, 'upperbound', [Inf Inf],'lowerbound',[0 0],'options',options)
pd(ii, jj, :) = p;=p; % store parameter values from mle
l=onestagepdf2(data,p(1),p(2)); % evaluate pdf with parameter values
ld(ii,jj)=sum(log(l)); % store likelihood value
end
end
Your pd was indeed the culprit, as #Trilarion stated, for the error you got. Probably ld also isn't too great, with the same syntax, so initialise that as well. This happened because parfor wants to know what the size of all variables within the loop is before executing. That this is a fixed maximum size is unknown to MATLAB, since you are using the loop variables to "change" the size.
Probably you had "orange wiggles" below those two lines (like spell-check errors) when you ran this as a for loop saying that "pd appears to be growing in size each iteration. Please consider preallocating for speed". This is required by parfor, since the order of iteration is not sequential it is impossible to grow arrays this way.
Secondly, you cannot nest parfor loops. You can use things like a function with a parfor and run that within the parfor, but that won't get you a speed-up since you are already using all your workers.
See Saving time and memory using parfor in Matlab? for more general information on parfor especially on speed.
You want a sliced, output variable but Matlab is not clever enough to detect that n*(i-1)+j is actually reasonable and won't interfere with an asynchronous evaluation.
Just do it as separate dimensions
pd = zeros(n, N, 2);
...
% in the loop
pd(i, j, :) = p;
That will work.
Please note, that Matlab does not allow nested parfors. However, you also do not need them if N is larger than the number of workers. See also the documentation.

Difficulties building vector of functions for fsolve

I am trying to implement a program using fsolve in matlab. I want the program to be able to compare n elements pairwise and where each comparison is a row in a function vector F of which fsolve is then applied to.
So far I have written the program for 3 elements (comparing 1 and 2,1 and 3, 2 and 3), writing each function explicitly which works as wanted. But I have now tried constructing the function vector in a loop inside a matlab function. However this does not seem to work since the function is called in every iteration of fsolve and therefore the values change in a unexpected way. Any advise on what could be done?
And the main program looks as follows:
A = [1 1;-1 -1;-1 1;1 -1];
U =[0 0];
Ustart= [6 7];
f= #(Uest)TimeDiffs(U,A,Ustart);
And the function TimeDiffs looks as follow:
function F = TimeDiffs(U,A,Uest)
F=[];
funcnum=1;
for q= 1:length(A)
for p= q+1:length(A)
td= norm(U-A(q,:))-norm(U-A(p,:));
F(funcnum)= norm(Uest-A(q,:))-norm(Uest-A(p,:))-td;
funcnum=funcnum+1;
end
end
end
There seems to be an issue when using a loop in a function that is used in fsolve. Has anyone had any similiar experience?

How can I calculate dyadics in matlab without using for loops?

I was wondering if someone could help me with my problem.
Let say that I have the coordinates of MxN vectors in a tensor r of dimensions [M,N,3]. I would like to save in a 3M-by-3N block matrix all dyadic products r_0'*r_0, where r_0 is the vector r_0 = r(m,n,:) for some m and n, and I would like to do this without using for loops.
If haven't explain myself correctly, here is an example code that shows what I would like to obtain (but using for loops, of course):
N=10;
M=5;
r=rand(M,N,3);
Dyadic=zeros(3*M,3*N);
for m=1:M
a1=3*m-2;
a2=3*m;
for n=1:N
b1=3*n-2;
b2=3*n;
aux(3)=r(m,n,3);
aux(2)=r(m,n,2);
aux(1)=r(m,n,1);
Dyadic(a1:a2,b1:b2)=transpose(aux)*aux
end
end
Thanks in advance!
You need to use bsxfun(#times and then re-arrange elements to have the desired output -
%// Get the multipliication result
mat_mult = bsxfun(#times,permute(r,[1 2 4 3]),r);
%// OR if you would like to keep mat_mult as 3D that could be potentially faster -
%// mat_mult = bsxfun(#times,reshape(r,[],3),permute(reshape(r,[],3),[1 3 2]));
%// Re-arrange elements to have them the way you are indexing in nested loops
Dyadic = reshape(permute(reshape(mat_mult,M,N,3,[]),[3 1 4 2]),M*3,N*3);
The major play about this solution is really the re-arrangement of elements after we have the multiplication result.
Quick runtime tests with the input r as 1000 x 1000 x 3 sized array, show that this bsxfun based approach gives over 20x speedup over the nested loop code listed in the question!

quickly find the indexes of common rows in two matrices

Thanks in advance for the help.
Suppose that I have two matrices: A and B. I want to know which rows in A are also in B. For example given
A = [1 2; 3 4] and B = [1 2; 5 6; 7 8]
I would like an output of
out = [1 0];
A simple way of doing this is to use for loops but my A and B matrices are both very large. Using for loops is thus exceedingly slow (it would likely take several hours to handle just two matrices and I have several thousand to compare). Is there a way that I could do this using Matlab's built-in functions (which are optimized to handle matrix operations)?
There is a way to do it with MATLAB's built-in functions!
out = ismember(A, B, 'rows');