2

I'm trying to use the parfor loop in the matlab parallelism package. I'm having a similar problem to this guy : MATLAB parfor slicing issue? . The output matrix doesn't seem to be recognized as a sliced variable. In my specific case, I'm trying to stack use other for loops inside the parfor, and I have trouble applying the solution proposed in the other thread to my problem. Here is a dummy example of what I'm trying to do :

n=175;
matlabpool;

Matred=zeros(n,n);

Matx2Cell = cell(n);

parfor i=1:n
    for j=1:n
        for k=1:n

            Matred(j,k)=exp((j+i+k)/500)
        end;
    end;
    Matx2Cell{i}=Matred;

end;
matlabpool close;

P.S. I know it would work to put the parfor on the k-loop instead of the i-loop... But I'd still like to put it on the i-loop (I believe it would be more time-efficient in my real program).

Thanks a lot Frédéric Godin

Community
  • 1
  • 1

2 Answers2

5

You can put Matred = zeros(n); into the parfor body, but this is very slow. Instead define a function with Matred = zeros(n); in it: effectively the same thing, but much faster:

function Matred = calcMatred(i,n)
Matred=zeros(n);
for j=1:n
    for k=1:n
        Matred(j,k)=exp((j+i+k)/500);
    end
end

Here is a time comparison:

matlabpool
n = 175;
Matx2Cell = cell(n,1);

tic
parfor i=1:n
    Matred=zeros(n);
    for j=1:n
        for k=1:n
            Matred(j,k)=exp((j+i+k)/500);
        end
    end
    Matx2Cell{i}=Matred;
end
toc

tic
parfor i=1:n
    Matx2Cell{i}=calcMatred(i,n);
end
toc

matlabpool close

On my machine, it takes 7 seconds for the first one and 0.3 seconds for the second.

Also note that I've changed the declaration of Matx2Cell to cell(n,1) since cell(n) makes an n x n cell array.

Ramashalanka
  • 8,564
  • 1
  • 35
  • 46
  • 1
    do you have an explanation why refactoring the code in a separate function is faster? – Amro Aug 17 '11 at 21:16
  • 3
    @Amro: the short answer is I don't know. I think it's because MATLAB doesn't then have to think about whether `Matred` is a loop, sliced, broadcast, reduction or temporary variable, since it is only in the function's workspace. I thought to do that when I saw the slowdown as I was preparing my answer; in the past I've found it best to make the contents of the `parfor` to be very simple by calling a function, since the dependencies are then obvious. Within the function you have great flexibility, e.g. you can call scripts, since the function has its own workspace. – Ramashalanka Aug 18 '11 at 04:29
  • +1 thank you that makes perfect sense. I guess I was hoping for a reference to the MATLAB documentation listing these kind of tips and recommended practices when doing parallel computations.. – Amro Aug 18 '11 at 11:35
  • Interesting indeed. After I saw your post, I immediately called BS until I tried it. Could not believe it. I'm tempted to bring this up with Mathworks, as it is an important tidbit I would like to fully understand. – Chris Aug 18 '11 at 16:17
  • @Ramashalanka I heard back from Mathworks. "The reason there is a difference in performance between two programs is due to the way the MATLAB Just In Time compiler (JIT) analyzes the sample codes. In the second case, JIT precompiles the code with the function. Therefore, during execution the compilation occurs only once and the code is re-used for every iteration of ‘parfor’. In contrast, the code fragment in the first case is interpreted by Matlab for every iteration of ‘parfor’ which results in slower execution." – Chris Aug 19 '11 at 21:06
  • @Chris: thanks for asking about that. I wonder if it's possible to predict that behavior from the documentation. – Ramashalanka Aug 20 '11 at 03:03
  • @Ramashalanka haha, yeah that was my first question too. I asked in a follow up so we will see... – Chris Aug 20 '11 at 04:59
  • @Ramashalanka, I got back: Unfortunately, there is no explicit way to 'force' the JIT to precompile instead of interpret. JIT always analyzes the program and compiles the parts it can handle. On an addition note, it is best to avoid writing code to take advantage of a particular JIT implementation, because this feature is constantly evolving. Code optimized for one particular release may not run as well in the next. However, following some general principles (Best MATLAB coding practices) like the ones suggested below should help you to write JIT-friendly code. – Chris Aug 22 '11 at 18:55
1

You need to move Matred into the parfor loop body. This needs to be done because each iteration of the parfor needs a new copy of Matred.

n=175;
matlabpool;

Matx2Cell = cell(n);

parfor i=1:n
    Matred=zeros(n,n);
    for j=1:n
        for k=1:n

            Matred(j,k)=exp((j+i+k)/500)
        end;
    end;
    Matx2Cell{i}=Matred;

end;
matlabpool close;
Chris
  • 1,532
  • 10
  • 19