Problem with cell array indexing when using parfor

17 次查看(过去 30 天)
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

采纳的回答

OCDER
OCDER 2018-5-21
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 个评论
OCDER
OCDER 2018-5-23
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!
Hayao
Hayao 2018-5-23
Thank you,
Actually, you are right. I should've tried normal "for" loop before testing parfor. I initially did not have (cycle) variables because I first made normal for-loop script. Seeing that the script works, but way too slow for cases with large matrix, I decided to use parfor.
Of course parfor didn't work at first because of write-access conflict issues. That is when I attempted changing the code using cell arrays with (cycle) to prevent the issue and then the "classify variable" error came up.
Thank you for your consistent help and being patient with me. I'll try rewriting the script in a little more organized manner with what you said in mind. I'll be back with a new question if problem persists with the reorganized new code.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Parallel for-Loops (parfor) 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by