Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

parfor loop with nested for loop

367 views
Skip to first unread message

Cindy

unread,
Jun 15, 2009, 1:16:01 PM6/15/09
to
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


Christian Hesch

unread,
Jun 15, 2009, 2:01:04 PM6/15/09
to
"Cindy" <xzh...@fhcrc.org> wrote in message <h15vkh$fia$1...@fred.mathworks.com>...

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?

Cindy

unread,
Jun 15, 2009, 2:28:01 PM6/15/09
to
"Christian Hesch" <&christi...@web.de> wrote in message <h1628v$a33$1...@fred.mathworks.com>...

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

Christian Hesch

unread,
Jun 15, 2009, 3:28:02 PM6/15/09
to
"Cindy" <xzh...@fhcrc.org> wrote in message <h163rh$qin$1...@fred.mathworks.com>...


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.

Raymond Norris

unread,
Jun 15, 2009, 3:54:01 PM6/15/09
to
Cindy,

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?

Cindy

unread,
Jun 15, 2009, 4:43:01 PM6/15/09
to
Thanks, Raymond and Christian! This makes sense. I had problem understanding the term 'slice variable' in the MATLAB document. I actually wants to generate the values for c from these loops. So combining the suggestions from both of you, maybe I should put

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>...

Christian Hesch

unread,
Jun 15, 2009, 5:09:02 PM6/15/09
to
This will be faster (at least, I hope so, depends on the size of m and n):

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(:);

Cindy

unread,
Jun 15, 2009, 5:19:03 PM6/15/09
to
I tried this. The same error message showed up. I think this is because j is not constant for the parfor, as noted by Raymond.

"Christian Hesch" <&christi...@web.de> wrote in message <h16d9e$1j5$1...@fred.mathworks.com>...

Christian Hesch

unread,
Jun 17, 2009, 1:30:19 AM6/17/09
to
"Cindy" <xzh...@fhcrc.org> wrote in message <h16ds7$bfv$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

0 new messages