matlabparallel-processingparfor

Broadcast arrays in parfor loops in MATLAB results in error


Below is a minimal working example of my problem that simply prints the loop indices when x!=1, and also does some extra operation when x==1.

x = 0;

if (x == 1)
    test_array = zeros(10, 10);
end

parfor i = 1:10
    if (x == 1)
        unused_variable = test_array(:, i);
    end

    fprintf('%i', i)
end
fprintf('\n')

The error I get is:

"Error: Invalid syntax for calling function 'test_array' on the path. Use a valid syntax or explicitly initialize 'test_array' to make it a variable."

I do not expect this code to give an error, although I do understand why I get a warning: "The entire array or structure 'test_array' is a broadcast variable. This might result in unnecessary communication overhead."

The code does not give an error when x=1, does not give an error when the (:, :) indexing is removed, does not give an error when test_array is initialised, and it also does not give an error when parfor is changed to for.

The above example is more simplified than the problem I am actually solving, and ultimately want to keep the repeated code logic for x==1 and x=!1 next to each other in the code if possible. Is the solution to instead copy-and-paste the code twice and have two parfor loops inside an if-else statement, or is there a better way to keep it in the above format? Thanks in advance.


Solution

  • The error you get is because the parser is not seeing test_array defined as a variable. It thus assumes it is a function call, and notes that you can't use : as an argument in a function call. test_array(:, i) is illegal if test_array is a function.

    The error message also gives you the solution: you need to explicitly make test_array a variable by initializing it.

    According to the comment by OP below, the indexing gets validated even if it will not be executed later. Thus, we need to initialize the variable to an array that can be indexed as done in the code.

    The smallest array for which test_array(:, i) is legal is a 0x10 array (according to Edric):

    if x == 1
        test_array = zeros(10, 10);
    else
        test_array = zeros(0, 10);
    end
    

    Note that this array has no data. Minimizing the unused array is relevant if the array otherwise is large, and you are using the process-based parallel pool, in which data has to be sent to the worker processes. In this case, we want to minimize the amount of data sent to keep things efficient.

    If the actual array is not too big (as in the example code), and/or you are using the thread-based parallel pool, then it is not necessary to make the array as small as possible, you can just create the same array for all cases:

    test_array = zeros(10, 10);