MATLAB Answers

parfor variable cannot be classified

4 views (last 30 days)
Hi,
I have a code which calculates the matrix elements of A from a vector v. It works well in the serial case. When I try to speed up the calculation using parfor, I get an error "The variable A in a parfor cannot be classified".
It seems that the program somehow cannot deal with the temporary variables as the indicies for the matrix A... Any suggestions or workaround for this?
A = zeros(n,n);
for kk = 1:D
sk = <expressions>;
ek = <expressions>;
parfor ll = 1:D
sl = <expressions>;
el = <expressions>;
if (ek == el)
A(sk,sl) = A(sk,sl)+conj(v(kk))*v(ll);
end
end
end

  0 Comments

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 8 Jul 2020
Sliced variables:
Form of Indexing. Within the first-level of indexing for a sliced variable, exactly one indexing expression is of the form i, i+k, i-k, or k+i. The index i is the loop variable and k is a scalar integer constant or a simple (non-indexed) broadcast variable. Every other indexing expression is a positive integer constant, a simple (non-indexed) broadcast variable, a nested for-loop index variable, colon, or end.
When you use sl as the index, since sl is not one of the above forms, then even if sl was calculated according to one of those forms, it is not a valid slice for parfor.
parfor ll = 1 : 5
LL3 = ll+3;
A(LL3) = 7; %not a valid slice!
A(ll+3) = 7; %valid slice
end
Your A is not the loop variable -- your loop variable is ll
Your A is not a broadcast variable -- broadcast variables cannot be assigned into inside the parfor.
Your A is not a temporary variable -- you initialize it outside the parfor and you probably use it after the parfor
And your A is not a reduction variable, because reduction variables cannot be indexed.
What can you do? Let us have a closer look
A(sk,sl) = A(sk,sl)+conj(v(kk))*v(ll);
sk is constant inside the parfor iteration. You can define
Ask = A(sk,:);
parfor ll=1:D
sl = <expressions>;
Askl = Ask(sl);
el = <expressions>;
if (ek == el)
Askl = Askl + conj(v(kk))*v(ll);
end
Ask(sl) = Askl;
end
This still will not work unless sl is one of the permitted forms, such as ll+3 . If it is one of the permitted forms then
Ask = A(sk,:);
parfor ll=1:D
Askl = Ask(explicit expression for sl);
el = <expressions>;
if (ek == el)
Askl = Askl + conj(v(kk))*v(ll);
end
Ask(explicit expression for sl) = Askl;
end
However, if it is not one of the permitted forms, then you have three possibilities:
  1. That sl is constant for all ll within any kk iteration. In this case you could convert the code into a reduction variable system
  2. That for any kk value, sl can be uniquely calculated based upon ll with no duplicate sl values for different ll values, and conversely that the mapping is reverseable. In this case, mapping of indices is possible;
  3. That for any given kk value, kk is not constant and is not unique for different ll. In this case, you might not be able to convert to parfor (but in some cases you could do it.)
The mapping technique I talked about:
You do not appear to use the current version of A(sk,sl) in the loop except to add to it. This tells us we could do:
for kk = 1:D
sk = <expressions>;
ek = <expressions>;
Ask = zeros(1,D);
parfor ll=1:D
el = <expressions>;
if (ek == el)
Ask(1,ll) = conj(v(kk))*v(ll);
end
end
for ll = 1 : D %not parfor
sl = expression in ll;
A(sk, sl) = A(sk, sl) + Ask(1,ll);
end
end

  3 Comments

Fermin Lung
Fermin Lung on 8 Jul 2020
Thanks! The suggested solution works and I now also have a better understanding on why my previous code didn't work. However, the computation time is slower than using an ordinary for loop....
Walter Roberson
Walter Roberson on 8 Jul 2020
It is common for the communication time and the time to set up the parallel pool to completely overwhelm savings you get from going multiple process.
Also, unless you are careful in your configuration, each parfor worker gets only one core, and so is not able to take advantage of automatic parallelization of vectorized code. In some cases the code sections have no significant vector computation and it does not matter, but a lot of the time the automatic multi-core vectorization savings add up. It is possible to configure more cores per worker in the parallel profile, provided that workers * cores_per_worker <= physical_cores (don't do logical cores; it will permit you to configure it, but it will slow down your computation.)

Sign in to comment.

More Answers (0)

Tags

Products

Community Treasure Hunt

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

Start Hunting!

Translated by