Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab parfor loop indexing

Tags:

matlab

parfor

Does anybody know what's going on in this simple code using parfor in matlab? Thanks,

I sliced a matrix into four arrays and want to update elements in each array independently

Here is a simple version:

a = zeros(4,4);  
parfor i = 1:4  
    j = 2;      
    a(j,i) = 3;  
end

error:Valid indices for 'a' are restricted in parfor loops;

however,

this works:

a = zeros(4,4);  
parfor i = 1:4  
    a(2,i) = 3;  
end

another simpler nonworking version with the same error:

a = zeros(4,4);  
parfor i = 1:4  
    a(i,i) = 3;  
end

in my application, index j is generated independently for each array through some algorithm

like image 522
Zongyi Gong Avatar asked Mar 22 '13 19:03

Zongyi Gong


3 Answers

Just my two cents: As @mmumbos already explained, what you're trying to achieve is not possible this way, but certain workarounds can still apply.

Let's assume you need to implement something like the following (which is the permutation of a linear transformation of matrix A):

n=10;
A=rand(n,n);
B=zeros(n,n);
parfor i=1:n,
  j=(i<=5)*(2*(i-1)+1)+(i>5)*(2*(i-5));
  B(j,i) = my_function(A(i,:));
end

Try instead the following:

parfor i=1:n,
  B_temp(i,:) = my_function(A(i,:));
end

Then, you don't really need to construct matrix B; you can access it using B_temp using an ''index table'' which is simply constructed as follows:

J=zeros(n,1);
parfor i=1:n,
  J(i) = (i<=5)*(2*(i-1)+1)+(i>5)*(2*(i-5));
end

Then B(i) is accessed via B_temp(J(i)).

Revisiting your last (counter)example, let's see how you can work it around:

n=4;
diag_A = zeros(n,1);
parfor i=1:n,
    diag_A(i)=3; % or any function of i
end

Then, whenever you need to access the ''i''-th diagonal element of A, you access instead diag_A(i). For such cases it is convenient to create a function along the following lines:

function a = access_matrix(A, diag_A, i, j)
  if (i!=j), 
    a = A(i,j);
  else
    a = diag_A(i);
  end
end

Until MATLAB improves the implementation of parfor, such workarounds will (unfortunately) be necessary in lots of cases.

like image 198
Pantelis Sopasakis Avatar answered Nov 13 '22 15:11

Pantelis Sopasakis


What you are trying to achieve seems not to be possible.

According to the matlab documentation:

When you use other variables along with the loop variable to index an array, you cannot set these variables inside the loop. In effect, such variables are constant over the execution of the entire parfor statement. You cannot combine the loop variable with itself to form an index expression.

MATLAB Documentation Source

So all variables you use to index your array, other than the loop variable have to be constant for the entire loop.

like image 39
mmumboss Avatar answered Nov 13 '22 14:11

mmumboss


Since it hasn't been mentioned yet, here's a link which is really helpful for diagnosing these types of issues: Classification of Variables in Parfor. These issues arise when MATLAB cannot classify the variables into the rigid definitions it outlines on that page.

What's happening here is that it does not know how to slice up the "slice variable" A before the loop. Think about programming the parallel implementation yourself. What you would want to do is cut-up A into even pieces that you know other processors won't touch, and then give them to different CPUs to act indpendently. MATLAB looks at your loop and doesn't know how to do this because it doesn't know what j is until it's running the program. It's a limitation of MATLAB. Another case where the same thing happens if you use complex coefficients like A(i*j,:). Once again it doesn't know how to split it up.

like image 1
Chris Rackauckas Avatar answered Nov 13 '22 16:11

Chris Rackauckas