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); |
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); % This function now contains the body % of the parfor-loop function means = computeMeans(data) y.mean = mean(data); means = y.mean; 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 (MATLAB). 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.