Reputation: 89
I am struggling with vectorizing this parfor loop. I want to completely remove the parfor loop from the code as it is taking a long time to execute when n is large. Please see the code pasted below. I will appreciate any tips/advice/help any person in this forum can give me on this. Many thanks in advance.
% Initialization and precomputations
% w is an n x 1 vector
% beta: any number larger than 0. Usually set to 1.
f = zeros(n,1);
x = w;
y = w;
rho = 1;
v = f – (rho*y);
rhow = rho*w;
n = length(w);
parfor i = 1 : n
if w(i) >= 0
if v(i) < -rhow(i) – beta – 1
x(i) = (-beta -1 -v(i))/rho;
elseif (-rhow(i) – beta – 1 <= v(i)) && (v(i) <= -rhow(i) + beta – 1)
x(i) = w(i);
elseif (-rhow(i) + beta – 1 < v(i)) && (v(i) < beta – 1)
x(i) = (beta – 1 -v(i))/rho;
elseif (beta – 1 <= v(i)) && (v(i) <= beta + 1)
x(i) = 0;
else
x(i) = (beta + 1 – v(i))/rho;
end
else
if v(i) < -beta -1
x(i) = (-beta -1 – v(i))/rho;
elseif (-beta – 1 <= v(i) )&& (v(i) <= -beta + 1)
x(i) = 0;
elseif (-beta + 1 < v(i)) && (v(i) < -rhow(i) – beta + 1)
x(i) = (-beta + 1 – v(i))/rho;
elseif (-rhow(i) – beta + 1 <= v(i)) && (v(i) <= -rhow(i) + beta + 1)
x(i) = w(i);
else
x(i) = (beta + 1 – v(i))/rho;
end
end
end
UPDATE: Thank you very much Hbderts for your answer, it helped me very much. This is what I finally came up with. I'm still getting something wrong because when I slot in values for the variables, I don't get the desired result as I have with the parfor loop. Can you help me look at it and let me know where I got it wrong? Many thanks in advance.
cond1 = (w >= 0);
cond2 = (w >= 0) & (v < -rhow-beta-1);
x(cond2) = (-beta-1-v(cond2))/rho;
cond3 = (w>=0)&(-rhow - beta -1 <= v) & (v <= -rhow + beta - 1);
x(cond3) = w(cond3);
cond4 = (w>=0) & (-rhow +beta - 1 < v) & (v < beta - 1);
x(cond4) = (beta - 1 - v(cond4))/rho;
cond5 = (w>=0) & (beta - 1 <= v) & (v <= beta + 1);
x(cond5) = 0;
cond6 = (~cond2);
x(cond6) = (beta + 1 - v(cond6))/rho;
cond7 = ((~cond1) & v < -beta -1);
x(cond7) = (-beta -1 - v(cond7))/rho;
cond8 = ((~cond1) & (-beta - 1 <= v) & (v <= -beta + 1));
x(cond8) = 0;
cond9 = ((~cond1) & (-beta + 1 < v) & (v < -rhow - beta + 1));
x(cond9) = (-beta + 1 - v(cond9))/rho;
cond10 = ((~cond1) & (-rhow - beta + 1 <= v) & (v <= -rhow + beta + 1));
x(cond10) = w(cond10);
cond11 = (~cond1);
x(cond11) = (beta + 1 - v(cond11))/rho;
Upvotes: 1
Views: 105
Reputation: 14316
You can use a logical vector to index a matrix, as described in the MATLAB help pages. Let's make a simple example:
A = [1 2 3 4];
ind = logical([0 1 0 1]);
B = A(ind)
B =
2 4
You can use this system to model all different cases and drop the for loop. For the first case, that would be
x((w>=0)&(v<-rhow-beta-1)) = (-beta-1-v((w>=0)&(v<-rhow-beta-1)))/rho;
Let's look at the term x((w>=0)&(v<-rhow-beta-1))
in detail:
w>=0
creates a logical vector containing 1
(true) if the corresponding entry in w
is >=0
and 0
(false) otherwise.v<-rhow-beta-1
also creates a logical vector, containing true or false.&
between these terms is a logic AND. With this we have a vector containing true for all elements wich meet both conditions, and false otherwise.x(...)
, we get all elements from x
, which meet both of the conditions above.Now we have all the elements which we want to set in the first step. We now have to create the values which we will set them to. The part (-beta-1-v(...))/rho
is the same as before. With v(...)
where ...
are the same conditions as before, we take all relevant v
's, do the calculation with them and save them in the correct position of x
.
We can repeat this procedure with all if-then-else clauses you have. For the second one, this will be
x((w>=0) & (-rhow–beta–1<=v) & (v<=-rhow+beta–1)) = ...
w((w>=0) & (-rhow-beta-1<=v) & (v<=-rhow+beta-1));
And so on...
Upvotes: 4