%% spmd basic examples
% spmd - single program, multiple data

%
%% spmd - Single Program Multiple data
% 
% In contrast to parfor-loops, each worker executing an spmd-statement is
% assigned a unique value of |labindex| that let's you address the worker
% explicitly.
%
% * An spmd block runs on the workers of the existing parallel pool. 
% If no pool exists, spmd will start a new parallel pool, unless the 
% automatic starting of pools is disabled in your parallel preferences. 
% If there is no parallel pool and spmd cannot start one, the code runs 
% serially in the client session.
% * There are two forms of indexing a Composite, comparable to indexing a 
%  cell array:
%
%   AA{n} returns the values of AA from worker n.
%
%   AA(n) returns a cell array of the content of AA from worker n
% 
%% First example
%
nlabs=4; % Classroom
nlabs=2; % 2-kernel-laptop
myPool = parpool(nlabs); 
% parpool % is enough
%%
spmd
    x = labindex+(-3:3)
end
%%
x
[x{1};x{2}]

%% Sum over workers:
spmd
   s = gplus(x)
   % s1 = gplus(x, 1)   % Return result (sum) in s1{1} only    
end
s

%%
[s{1},s{2}]
%%
% ans =
%    3  3   
%
%% Catenate: gcat
spmd
    y1 = gcat(x, 1); % Concatenate along rows.
    y2 = gcat(x, 2); % Concatenate along columns.
end
y1{1}
y2{1}
%% Values from workers to client
v=[x{1} x{2}]
class(v)
class(x)
%% More generally
V=cell(1,2)
V(1:2)=x(1:2)
class(V)
%%
class(x)
%
%% Another example
% spmd(3)  % This is one way of choosing nr. of workers 
spmd(2)    % 2 is default for laptop, thus is not needed
    if labindex==1
      R=rand(3,3);  % On worker #1
    else
      R=magic(4);   % On workers #2 (and #3)
    end  
end
%%
R
%%
% Values computed inside the spmd-statement's body are returned in the form
% of *Composite object* on the client. It contains references to the values
% stored in the remote workers. These values can be retrieved using
% cell-array indexing, as noted above.
R{1:2}
%%
% The values are retained until the pool is closed.
% As shown above, the values can be brought to the client as a cell array:
RR=cell(2,1);
RR(:)=R(:)
% After the pool is closed, composite objects disapper, the cell arrays 
% (like RR) remain.
%%
delete(gcp)
%%
% R{:}  % Leads to error.
%%
RR{:}

%% spmd can do mpmd --  Multiple programs possible 
%
flist={@cos,@sin}
data1=(-pi:0.1:0)';
data2=(0:0.1:pi)';
datalist={data1,data2};
%%
spmd
   y= flist{labindex}(datalist{labindex});
end  
%%
subplot(2,1,1)
 plot(data1,y{1})
subplot(2,1,2)
 plot(data2,y{2})
shg
% One way of piecewise plotting. 
%
%%
% NOTE: Instead of cos and sin one can have extensive programs.
%%
delete(gcp)
