parfor
-Loopsparfor
-Loop Variables Are Consecutive Increasing IntegersLoop variables in a parfor
-loop must be consecutive increasing
integers. For this reason, the following examples return
errors:
parfor i = 0:0.2:1 % not integers parfor j = 1:2:11 % not consecutive parfor k = 12:-1:1 % not increasing
iValues = 0:0.2:1; parfor idx = 1:numel(iValues) i = iValues(idx); ... end
parfor
-LoopsIf MATLAB® detects that the parfor
-loop variable can overflow,
it reports an error.
Overflow condition | Example | Solution |
---|---|---|
The length of the | Here, MATLAB reports an error because
parfor idx=int8(-128:127) idx; end | Use a larger data type for the parfor idx=-128:127 int8(idx); end |
The initial value of the | Here, MATLAB reports an error because
parfor idx=uint32(0:1) idx; end |
|
parfor
-LoopsWhen MATLAB recognizes a name in a parfor
-loop as a variable,
the variable is classified in one of several categories, shown in the following
table. Make sure that your variables are uniquely classified and meet the category
requirements. parfor
-loops that violate the requirement return an
error.
Classification | Description |
---|---|
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 |
To find out which variables you have, examine the code fragment. All variable classifications in the table are represented in this code:
If you run into variable classification problems, consider these approaches before
you resort to the more difficult method of converting the body of a
parfor
-loop into a function.
If you use a nested for
-loop to index into a sliced
array, you cannot use that array elsewhere in the
parfor
-loop. The code on the left does not work because
A
is sliced and indexed inside the nested
for
-loop. The code on the right works because
v
is assigned to A
outside the
nested loop. You can compute an entire row, and then perform a single
assignment into the sliced output.
Invalid | Valid |
---|---|
A = zeros(4, 10); parfor i = 1:4 for j = 1:10 A(i, j) = i + j; end disp(A(i, 1)) end |
A = zeros(4, 10); parfor i = 1:4 v = zeros(1, 10); for j = 1:10 v(j) = i + j; end disp(v(1)) A(i, :) = v; end |
The code on the left does not work because the variable
x
in parfor
cannot be
classified. This variable cannot be classified because there are multiple
assignments to different parts of x
. Therefore
parfor
cannot determine whether there is a
dependency between iterations of the loop. The code on the right works
because you completely overwrite the value of x
.
parfor
can now determine unambiguously that
x
is a temporary variable.
Invalid | Valid |
---|---|
parfor idx = 1:10 x(1) = 7; x(2) = 8; out(idx) = sum(x); end |
parfor idx = 1:10 x = [7, 8]; out(idx) = sum(x); end |
This example shows how to slice the field of a structured array. See
struct
for details. The code
on the left does not work because the variable a
in
parfor
cannot be classified. This variable cannot
be classified because the form of indexing is not valid for a sliced
variable. The first level of indexing is not the sliced indexing operation,
even though the field x
of a
appears to be sliced correctly. The code on the right works because you
extract the field of the struct
into a separate
variable tmpx
. parfor
can now
determine correctly that this variable is sliced. In general, you cannot use
fields of struct
s or properties of objects as sliced
input or output variables in parfor
.
Invalid | Valid |
---|---|
a.x = []; parfor idx = 1:10 a.x(idx) = 7; end |
tmpx = []; parfor idx = 1:10 tmpx(idx) = 7; end a.x = tmpx; |
You cannot create a structure in a parfor
-loop using dot
notation assignment. In the code on the left, both lines inside the loop
generate a classification error. In the code on the right, as a workaround you
can use the struct
function to create the
structure in the loop or in the first field.
Invalid | Valid |
---|---|
parfor i = 1:4 temp.myfield1 = rand(); temp.myfield2 = i; end |
parfor i = 1:4 temp = struct(); temp.myfield1 = rand(); temp.myfield2 = i; end parfor i = 1:4 temp = struct('myfield1',rand(),'myfield2',i); end |
You cannot use structure fields as sliced input or output
arrays in a parfor
-loop. In other words, you cannot use the
loop variable to index the elements of a structure field. In the code on the
left, both lines in the loop generate a classification error because of the
indexing. In the code on the right, as a workaround for sliced output, you
employ separate sliced arrays in the loop. Then you assign the structure fields
after the loop is complete.
Invalid | Valid |
---|---|
parfor i = 1:4 outputData.outArray1(i) = 1/i; outputData.outArray2(i) = i^2; end |
parfor i = 1:4 outArray1(i) = 1/i; outArray2(i) = i^2; end outputData = struct('outArray1',outArray1,'outArray2',outArray2); |
The workaround for sliced input is to assign the structure field to a separate array before the loop. You can use that new array for the sliced input.
inArray1 = inputData.inArray1; inArray2 = inputData.inArray2; parfor i = 1:4 temp1 = inArray1(i); temp2 = inArray2(i); end
parfor
-Loop into a FunctionIf all else fails, you can usually solve variable classification problems in
parfor
-loops by converting the body of the
parfor
-loop into a function. In the code on the left, Code
Analyzer flags a problem with variable y, but cannot resolve
it. In the code on the right, you solve this problem by converting the body of the
parfor
-loop into a function.
Invalid | Valid |
---|---|
function parfor_loop_body_bad data = rand(5,5); means = zeros(1,5); parfor i = 1:5 % Code Analyzer flags problem % with variable y below y.mean = mean(data(:,i)); means(i) = y.mean; end disp(means); end |
function parfor_loop_body_good data = rand(5,5); means = zeros(1,5); parfor i = 1:5 % Call a function instead means(i) = computeMeans(data(:,i)); end disp(means); end % This function now contains the body % of the parfor-loop function means = computeMeans(data) y.mean = mean(data); means = y.mean; end Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers. 0.6786 0.5691 0.6742 0.6462 0.6307 |
If you use a name that MATLAB cannot unambiguously distinguish as a variable
inside a parfor
-loop, at parse time MATLAB assumes you are
referencing a function. Then at run-time, if the function cannot be found, MATLAB
generates an error. See Variable Names. For example,
in the following code f(5)
could refer either to the fifth
element of an array named f
, or to a function named
f
with an argument of 5
. If
f
is not clearly defined as a variable in the code, MATLAB
looks for the function f
on the path when the code runs.
parfor i = 1:n ... a = f(5); ... end
parfor
-loopsThe body of a parfor
-loop must be
transparent: all references to variables must be
“visible” in the text of the code. For more details about
transparency, see Ensure Transparency in parfor-Loops or spmd Statements.
The body of a parfor
-loop cannot contain global
or persistent
variable
declarations.