"valid indices for 'a' are restricted in PARFOR loops" for unindexed struct?
Show older comments
For the following code:
parfor k = 1:2
a.b = k;
end
I'm getting the error "valid indices for 'a' are restricted in PARFOR loops"
But there is no indexing here. Could someone explain what I'm missing?
In case it's important, the code above comprises the entire script.
You cannot create a structure in a parfor-loop using dot notation assignment.
It's not clear why, though.
Edit 2: Mathworks support has submitted an enhancement request to update the error message to something clearer in a future release.
MATLAB Version: 9.1.0.441655 (R2016b)
Answers (1)
parfor k = 1:2
a(k).b = k;
end
The reason a.b = k does NOT work is because when the parfor finishes, and there are, say N workers creating 1000 parallel versions of a.b = k, which one is going to be the final a.b? If 1000's of parallel universes converge into 1 universe, which universe will we be the "real" universe? Error error.
But, a(k).b = k works because each worker creates its own separate variable (or isolated universe), a(1).b, a(2).b, ..., a(N).b. No conflict issues.
In the example, this works too because temp is defined inside the parfor, which tell matlab "this is a temporary variable that's created in the parallel world - do not bring it to the real world"
parfor i = 1:4
temp = struct(); %What's created in the parallel world stays in the parallel world
temp.myfield1 = rand();
temp.myfield2 = i;
end
7 Comments
See the 2nd explanation about variables defined inside the parfor. I was typing that one up.
It depends on what variables you want to extract after the parfor completes. Variables defined inside the parfor stays in parfor, unless you put it into a sliced variable, which makes it clear to Matlab you want to take that variable outside of the parfor.
a = 1;
parfor k = 1:10
a= k
end
a
= 1 %(It doesn't take "a" defined inside parfor to the outside world)
parfor k = 1:10
a(k) = k
end
a
= [1 2 3 4 5 6 7 8 9 10] %(It takes the value of "a" outside, into the real world)
OCDER
on 16 Jul 2018
I guess I should have first asked - why are you creating structures inside a for/parfor loop?
Steven Lord
on 16 Jul 2018
a.b=k is a sliced variable
No, it's not. The characteristics a variable in a parfor loop must have in order to be a sliced variable, according to the documentation, are:
- Type of First-Level Indexing — The first level of indexing is either parentheses, (), or braces, {}.
- Fixed Index Listing — Within the first-level parentheses or braces, the list of indices is the same for all occurrences of a given variable.
- Form of Indexing — Within the list of indices for the variable, exactly one index involves the loop variable.
- Shape of Array — The array maintains a constant shape. In assigning to a sliced variable, the right side of the assignment cannot be [] or '', because these operators attempt to delete elements.
Your code, a.b = k, fails the first characteristic. In fact, the first "Reference for Variable Not Sliced" example in that section of the documentation page is your example, except that the documentation example uses the names A and x instead of a and b respectively.
Note that in the "Structure Arrays in parfor-Loops" section on this documentation page, the "valid" code makes a temporary variable, not a sliced variable. To slice, you need to do what's in the "Slicing Structure Fields" sub-section of that section of the page.
OCDER
on 16 Jul 2018
More examples for clarity (or confusion).
parfor k = 1:10 %<=== look for the iterator, 'k'
a(k) % sliced, I see a direct use of 'k'
a(k).b % sliced, I see a direct use of 'k' in the 1st level of a struct
a.b % NOT sliced. No use of 'k' anywhere
a.b(k) % Tricky. Not sliced at the 1st lv of struct 'a', but is sliced at 2nd lv 'a.b'.
% Matlab doesn't know if you want to save 'a' or treat as temporary var
a(k).b(k) % Tricky. Sliced variable! Sliced at 1st lv of struct a.
end
Hmm, yeah, the explanation isn't obvious as to why a.b = k is not just assumed to be a temporary variable. My guess is that structures are normally assumed to behave like objects that persistent across iteration, but parfor makes this assumption invalid. To prevent confusion, users have to be VERY CLEAR they know this structure will delete after each iteration unless it's sliced.
for j = 1:10
a.b = j; %structure "a" is created when j == 1, and it persists from here on out.
%a.b = 10 when loop finishes. No ambiguity.
end
parfor j = 1:10
a.b = j; %structure a is created 10 times at random order! a.b = 10, a.b = 2, ... a.b = 5.
%How do we assemble this back to a single "a" structure?
%Should this even be a single structure as an output?
%Was this a temporary variable?
%Let's just make this throw an error. Unclear how to return "a".
end
Categories
Find more on Matrix Indexing 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!