Problem with cell array indexing when using parfor
12 views (last 30 days)
Show older comments
Dear all,
I'm try to do certain calculation that automatically generates a certain (large) matrix for each iteration and calculates the Eigenvalue for it. To speed up the lengthy calculation, I am using parfor. Unfortunately, the code gives me "The variable IM in a parfor cannot be classified" error. It seems like looking at M-lint tells me that IM, B1, B2, and B3 are bad variables. These are all cell arrays that were created so that different cell can be assigned independently by each iteration, preventing interaction between other iterations.
I do not understand the problem here. Could someone help me? Thank you.
The code is shown below. IM, IIM, B1, B2, and B3 are already defined elsewhere as empty cell arrays. variables l and n depends on the input of the user but is defined prior to the code.
parfor cycle = 1:n
IM{cycle, 1} = IIM
B1{cycle, 1} = setdiff(1:(2*l+1)^3, ((2*l+1)^3+1)/2).'
if Impurity == 1
o(cycle) = randi([0, 1], 1);
if o(cycle) == 0
B2{cycle, 1} = 0;
else
p(cycle) = randi(length(B1{cycle, 1}),1);
IM{cycle, 1}(:, B1{cycle, 1}(p(cycle), 1)) = 0;
IM{cycle, 1}(B1{cycle, 1}(p(cycle), 1), :) = IM{B1{p(cycle),1}, :}*1;
IM{cycle, 1}(B1{cycle, 1}(p(cycle), 1), B1{cycle, 1}(p(cycle), 1)) = -str2double(answer3(2,1));
B2{cycle, 1} = B1{cycle, 1}(p(cycle), 1);
end
end
B3{cycle, 1} = zeros(m,1);
q(cycle) = 1;
while length(B1{cycle, 1}) > o(cycle) + str2double(answer2(1,1)) - 1
r(cycle) = randi(length(B1{cycle, 1}),1);
if B1{r(cycle), 1} ~= B2{cycle, 1}
B3{cycle, 1}(q(cycle),1) = B1{cycle, 1}(r(cycle), 1);
B1{r(cycle), 1} = [];
IM{:, B3{q(cycle), 1}} = 0;
IM{B3{q(cycle), 1}, :} = 0;
q(cycle) = q(cycle) + 1;
end
end
B1{cycle, 1}(B1{cycle, 1}==B2{cycle, 1}) = [];
for q = 1:length(B1{cycle, 1})
IM{B1{cycle, 1}(q(cycle), 1), B1{cycle, 1}(q(cycle), 1)} = 0;
IM{B1{cycle, 1}(q(cycle), 1), B1{cycle, 1}(q(cycle), 1)} = -(str2double(answer3(1,1)) + str2double(answer3(2,1)) + sum(IM{cycle, 1}(:, B1{q(cycle),1}))) + str2double(answer3(6,1))*sum(IM{cycle, 1}(:, B1{q(cycle),1}));
end
IM{cycle, 1}(((2*l+1)^3+1)/2, ((2*l+1)^3+1)/2) = 0;
IM{cycle, 1}(((2*l+1)^3+1)/2, ((2*l+1)^3+1)/2) = -(str2double(answer3(1,1)) + str2double(answer3(2,1)) + sum(IM{cycle, 1}(:, ((2*l+1)^3+1)/2)) + str2double(answer3(6,1))*sum(IM{cycle, 1}(:, ((2*l+1)^3+1)/2)))
I = eye((2*l+1)^3);
C = zeros((2*l+1)^3, 1);
C(((2*l+1)^3+1)/2) = 1;
[P{cycle,1},D{cycle,1}] = eig(IM{cycle,1})
V{cycle,1} = (P{cycle,1}*expm((D{cycle,1})*t)*(P{cycle,1})^-1)*C
S1(cycle) = sum(V{cycle,1}(B1{q(cycle),1},1)) + V{cycle,1}(((2*l+1)^3+1)/2,1);
end
0 Comments
Accepted Answer
OCDER
on 21 May 2018
On first glance, here are some issues. Rewrite the code to prevent accessing cells in dependent or ambiguous manners.
Example 1) Use the same indexing style for all variables linked to the parfor index. For instance:
IM = cell(1, 100);
parfor j = 1:numel(IM)
IM{j} = zeros(1, 10);%You're access IM via IM{j}. Must be same in code.
for k = 1:10
IM{j}(k) = k; %OKAY, same indexing style as IM{j}
IM{1, j}(k) = k; %NOT OKAY. Different indexing IM{1, j} even
%though it's correct without parfor.
end
end
Example 2) Don't modify a sliced variable with different index as the parfor counter, since MATLAB cannot confirm if these are truly independent.
B1 = cell(1, 100);
parfor j = 1:numel(B1)
r(j) = randi(numel(B1), 1);
B1{r(j)} = j; %NOT OKAY. Index to sliced variable B1 differs from
%parfor loop counter variable j. Conflict arises when
%multiple jobs tries to write to same cell in B1.
end
5 Comments
OCDER
on 23 May 2018
Interesting situation here... Did it work? If not, does this even work for a regular for loop?
There seems to be a lot of work needed to remove the typos and ensure each cycle is truly independent of each other.
To help, anytime you see the cycle parfor loop counter variable, check to see if the variable that uses cycle as an index is a sliced variable or a broadcast variable as intended. I see a lot of use of cycle...
I did find another potential error:
q(cycle) = 1;
...
for q = 1:length(B1{cycle, 1}) %HERE! q was a sliced variable, but now it's a counter variable. q(cycle) won't make sense.
IM{B1{cycle, 1}(q(cycle), 1), B1{cycle, 1}(q(cycle), 1)} = 0;
IM{B1{cycle, 1}(q(cycle), 1), B1{cycle, 1}(q(cycle), 1)} = -(str2double(answer3(1,1)) + str2double(answer3(2,1)) + sum(IM{cycle, 1}(:, B1{q(cycle),1}))) + str2double(answer3(6,1))*sum(IM{cycle, 1}(:, B1{q(cycle),1}));
end
Also, try to avoid having B1 (a sliced variable) storing another sliced variable inside. I feel like this is a fairly complex code structure...
B1{cycle, 1}(r(cycle), 1)
B1 = sliced variable itself
B1{cycle, 1} = sliced variable stored within a cell of B1?
r = sliced variable?
So are you trying to modify a sliced variable inside a sliced variable randomly,
and store this random variable in another sliced variable?
I'm having difficulty classifying which variables are sliced or broadcast or slices of sliced variables, which is probably the error Matlab is trying to tell you "Cannot classify variable IM".
Anyways, hope this helps!
More Answers (0)
See Also
Categories
Find more on Parallel for-Loops (parfor) in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!