Use Objects and Handles in parfor-Loops

Using Objects in parfor-Loops

If you are passing objects into or out of a parfor-loop, the objects must properly facilitate being saved and loaded. For more information, see Save and Load Process for Objects.

You cannot slice the fields of objects because of first-level indexing constraints. For details, see Sliced Variables.

For example, 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.

InvalidValid
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);

Handle Classes

You can send handle objects as inputs to the body of a parfor-loop. However, any changes made to handle objects on the workers during loop iterations are not automatically propagated back to the client. That is, changes made inside the loop are not automatically reflected after the loop.

To get the changes back to the client after the loop, explicitly assign the modified handle objects to output variables of the parfor-loop. In the following example, maps is a sliced input/output variable.

maps = {containers.Map(),containers.Map(),containers.Map()}; 
parfor ii = 1:numel(maps)
    mymap = maps{ii};   % input slice assigned to local copy
    for jj = 1:1000
        mymap(num2str(jj)) = rand;
    end
    maps{ii} = mymap;   % modified local copy assigned to output slice
end

Sliced Variables Referencing Function Handles

You cannot directly call a function handle with the loop index as an input argument, because this variable cannot be distinguished from a sliced input variable. If you must call a function handle with the loop index variable as an argument, use feval.

The following example uses a function handle and a for-loop.

B = @sin;
for ii = 1:100
    A(ii) = B(ii);
end

A corresponding parfor-loop does not allow B to reference a function handle. You can work around the problem using feval.

B = @sin;
parfor ii = 1:100
    A(ii) = feval(B,ii);
end

Related Topics