Keep a temporary variable after parfor
33 views (last 30 days)
Show older comments
I am just wondering how do I keep my value z after the parfor has run?
% x (real(c))
tic;
ticBytes(gcp);
dx=0.01; % step
x1=-2;
x2=2;
% y (imag(c))
dy=0.01; % step
y1=-1.5;
y2=1.5;
x=x1:dx:x2;
y=y1:dy:y2;
[X,Y] = meshgrid(x,y); % for vectorized calculation
c=X+1i*Y;
R=1000; % if abs(z)>R then z is considered as infinity
n=1000; % maximal number of iterations, 100 is close to infinity
parfor nc=1:n
z=zeros(size(c)); % starts from zeros
z=z.^2+c; % vectorized
end
I=abs(z)<R; % logical image
imagesc(x,y,I);
colormap((jet));
set(gca,'XColor', 'none','YColor','none');
toc;
tocBytes(gcp);
7 Comments
Paul Hoffrichter
on 7 Apr 2021
>> go into the intracacies of sliced and reducation variables
I have an idea where you are going with this, and would appreciate whether you think it would work in the parfor loop. Given the square of s within the parfor loop, I did not think that s could be broken into chunks for each of the parfor workers since the workers would not know how to initialize s properly in each of the workers' processes. I try to explain why I cam to this conclusion in my posts below.
Accepted Answer
Paul Hoffrichter
on 7 Apr 2021
Edited: Paul Hoffrichter
on 7 Apr 2021
>> Parfor loop works when i comment out the plotting parts of the code.
I tried what you said and only experienced what you wrote when I forgot to clear the z-matrix after the previous run. Otherwise, it did not work. Were you leaving around your prevoius z?
Your loop appears to be trying to accumulate a value across an iteration of the loop, regardless of the iteration order. Using Matlab terminology, you wanted your z-matrix to be a reduction variable, rather than a temporary variable.
"Reduction Variables: Variables that accumulates a value across iterations of the loop, regardless of iteration order"
Ref: https://www.mathworks.com/help/parallel-computing/troubleshoot-variables-in-parfor-loops.html
"Another common cause of uninitialized temporaries can arise when you have a variable that you intended to be a reduction variable. However, if you use it elsewhere in the loop, then it is classified as a temporary variable."
Ref: https://www.mathworks.com/help/parallel-computing/temporary-variable.html
Consider these two loops:
s = 0;
constant = 1;
for ii = 1:100
s = s + constant; % i.e., s(n) = s(n-1) + constant;
end
>> s
s =
100
s = 0;
constant = 1;
parfor ii = 1:100
s = s + constant; % i.e., s(n) = s(n-1) + constant;
end
>> s
s =
100
No Matlab errors. Despite the current value of s in the loop being dependent upon the previous value, the Matlab parfor analyzer could see that each parfor worker could initialize its value of s to 0, and then add together the results after all the workers have accumulated their sums. The variable s in this case is called a "reduction" variable.
But in your case, you have:
s = s.^2 + constant;
Because of the squaring, only one worker would know how to initialize the value of s. To initialize the other workers' s-values, a worker would have to compute it knowing its ii-chunk. But that defeats the purpose of parfor.
To see the issue:
s1 = s0.^2 + c;
s2 = s1.^2 + c = (s0.^2 + c).^2 + c = s0.^4 + 2*c*s0.^2 + c.^2 + c; % looking hard to compute for another worker
s3 = s2.^2 + c = (s0.^4 + 2*c*s0.^2 + c.^2 + c).^2 + c; % a parfor worker would give up on initial conditions for s.
4 Comments
Paul Hoffrichter
on 7 Apr 2021
Edited: Paul Hoffrichter
on 7 Apr 2021
Sorry that I did not read you reply before I wrote down my second post with my conclusion.
>> you're saying its being used as a reduction value until it is being called in the next line of code
What I was trying to say is that it appeared to me that you were hoping that z would be a reduction variable, in which case, the parfor would work. But, in fact, it never achieved that status because of the z-squaring. This squaring makes the separate independent workers impossible to initialize s in their own worker's process.
Here is one way, in the future, to try to manually figure out whether a parfor can work. See if you can break down a for loop in just, say, 2 chunks (e.g., 1:N/2 and N/2+1:N), and the see how you should initialize the variables whos values are needed after the two workers have completed their portion of the parfor-loop. Then, at the parfor end-line, can you figure out how to put the two results together to form the desired answer. Even in the simple case where
z = z + constant; % i.e., z(n) = z(n-1) + constant;
it is not immediately obvious (to me) that it can be done, but with a pencil and paper, I am able to prove it possible. Or, you can keep this as a referece for the classifications of variables inside a parfor-loop:
Loop Variables Loop indices
Sliced Variables Arrays whose segments are operated on by different iterations of the loop
Broadcast Variables Variables defined before the loop whose value is required inside the loop, but never assigned inside the loop
Reduction Variables Variables that accumulates a value across iterations of the loop, regardless of iteration order
Temporary Variables Variables created inside the loop, and not accessed outside the loop
One last note. Your line of code in the parfor loop is that of a difference equation. If you can figure out how to make z a closed function of (x,y), then you will not need any loop at all.
Raymond Norris
on 8 Apr 2021
Reduction variables are broken into two parts. Let's take the following example
z = 10;
constant = 5;
parpool(4);
parfor idx = 1:400
z = z + constant;
end
parfor will send n chunks to each of the 4 workers. Let's assume that first chunk is n=50. Each worker is going to add constant to the addition identity matrix (i.e. 0) n times.
worker 1
local_z = 0; % Because 0 is the addition identity matrix
for ii=1:50
local_z = local_z+constant
end
worker 2
local_z = 0;
for ii=1:50
local_z = local_z+constant
end
ditto for worker 3 and worker 4.
Once a worker is done, it'll get its next chunk, let's say n=25
local_z = 0;
for ii=1:25
local_z = local_z+constant
end
Eventually, all 400 iterations are complete and each worker has a local summation. Let's assume each worker has done the same, then each local sum is 500. Then parfor does a final summation of the initial value (10) and each of the workers: 10 + 500 + 500 + 500 + 500 = 2010.
This is similar for
z = z * constant;
where we use the multiplication identity matrix (1).
More Answers (0)
See Also
Categories
Find more on Parallel for-Loops (parfor) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!