I just got a parallel toolbox and trying to modify my previous serial program. Can parfor loop be nested with a for loop like the following?
c = zeros(m*n+1);
parfor i = 1:m
for j = 1:n
id = (i-1)*n+j;
c(id) = id;
end
end
I got a error message saying "valid indices for 'c' are restricted in parfor loops". Does this mean I have to change this nested loop to a single loop? Is there a simpler way?
Thanks!
Cindy
If i see it right, this loop does nothing else then c = 1:m*n. The error message is right, since the parallel computing toolbox only adresses directly, i.e. c(i,j) but not c(i*j). Mayby you specify the loop you try to program exactly, so I can help?
Hi Christian,
Thanks for the reply. You are right, this loop is simply c = 1:m*n. Actually, I meant c to be a vector m*n by 1. sorry for the typo. The following is more closely to the real program,
c = zeros(m*n,1);
parfor i = 1:m
for j = 1:n
id = (i-1)*n+j;
c(id) = func(id); (**)
end
end
and func is some complicated. But even for the simplest one, like in the original post, it shows error message.
I do not understand why parallel tool box can not address c(id). If I change the line(**) by disp(c(id)), then there is no error message. So it can only read but not write?
Thanks,-Cindy
You are right, you can read but not always write. You have to consider, that within a parfor loop different processors are acting on a single array of datas. For reading, the values can be copied, for writing the schedulers has to assure, that the data get not corrupted, i.e. that the different processors does not try to write data on the same element of the array (so called running condition). Although this doesn't happend within your construction, Matlab is not able to check it before. This is why you get the error message.
Try the following:
c1 = zeros(m,n);
parfor i = 1:m
for j = 1:n
id = (i-1)*n+j;
c1(i,j) = func(id); (**) % Maybe you can vectorize here a little bit
end
end
c2 = zeros(m*n,1);
for i = 1:m
c2((1:m)+(i-1)*n) = c1(i,:);
end
This should work.
The variable "c" is, in essence, a sliced output variable or you're trying to modify a broadcast variable. If it's a sliced output variable, it must be indexed with either the the loop variable, i, or with a constant variable, defined outside the parfor loop. You can't update a broadcast variable since the value is sent out once to each worker.
Something to consider is what are you doing with "c" after the parfor. Could you assign
c = zeros...
inside the parfor loop. Then it becomes just a temporary variable inside the parfor (you won't be able to access its value after the parfor).
Addressing your question about accessing "c" from the RHS. Take the following example:
c = zeros(10);
parfor idx = 1:10
j = rem(10,idx)+1;
k = c(j);
end
In this case, "c" is a broadcast variable, that happens to be indexed in the body of the code. "c" is not a sliced input variable. To make it a sliced input variable, you'd need to slice it with "idx", not "j".
Raymond
"Cindy" <xzh...@fhcrc.org> wrote in message <h163rh$qin$1...@fred.mathworks.com>...
> "Christian Hesch" <&christi...@web.de> wrote in message <h1628v$a33$1...@fred.mathworks.com>...
> > "Cindy" <xzh...@fhcrc.org> wrote in message <h15vkh$fia$1...@fred.mathworks.com>...
> > > Hi All
> > >
> > > I just got a parallel toolbox and trying to modify my previous serial program. Can parfor loop be nested with a for loop like the following?
> > >
> > > c = zeros(m*n+1);
> > > parfor i = 1:m
> > > for j = 1:n
> > > id = (i-1)*n+j;
> > > c(id) = id;
> > > end
> > > end
> > >
> > > I got a error message saying "valid indices for 'c' are restricted in parfor loops". Does this mean I have to change this nested loop to a single loop? Is there a simpler way?
> > >
> > > Thanks!
> > > Cindy
> > >
> > >
> >
> > If i see it right, this loop does nothing else then c = 1:m*n. The error message is right, since the parallel computing toolbox only addresses directly, i.e. c(i,j) but not c(i*j). Maybe you specify the loop you try to program exactly, so I can help?
c = zeros(m,n)
for j=1:n
parfor i = 1:m
id = (i-1)*n+j;
c(i,j) = func(id);
end
end
func2(c);
Here I am assuming m>n. This works for me for now. Thanks!
-Cindy
"Raymond Norris" <raymond...@mathworks.com> wrote in message <h168sp$6pk$1...@fred.mathworks.com>...
c1 = zeros(m,n);
parfor i = 1:m
for j = 1:n
id = (i-1)*n+j;
c1(i,j) = func(id);
end
end
c = c1(:);
"Christian Hesch" <&christi...@web.de> wrote in message <h16d9e$1j5$1...@fred.mathworks.com>...
Your are right, hadn't had a matlab to control it. Try this:
c1 = zeros(m,n);
parfor i = 1:m
c1(i,:)=test(i);
end
c = c1(:);
With the function:
function c= test(i,n)
c = zeros(1,n);
for j = 1:n
id = (i-1)*n+j;
c(1,j) = id;
end