Numerical Estimation of Pi Using Message Passing

This example shows the basics of working with spmd statements, and how they provide an interactive means of performing parallel computations. We do this by performing relatively simple computations to approximate pi.

Related Documentation:

Related Examples:

The code shown in this example can be found in this function:

function paralleldemo_quadpi_mpi

Introduction

We intend to use the fact that

to approximate pi by approximating the integral on the left.

We intend to have the parallel pool perform the calculations in parallel, and to use the spmd keyword to mark the parallel blocks of code. We first look at the size of the parallel pool that is currently open.

p = gcp;
p.NumWorkers
ans =

    12

Parallelize the Computations

We approximate pi by the numerical integral of 4/(1 + x^2) from 0 to 1.

type pctdemo_aux_quadpi.m
function y = pctdemo_aux_quadpi(x)
%PCTDEMO_AUX_QUADPI Return data to approximate pi.
%   Helper function used to approximate pi.  This is the derivative 
%   of 4*atan(x).

%   Copyright 2008 The MathWorks, Inc.
y = 4./(1 + x.^2);

We divide the work between the workers (labs) by having each worker calculate the integral of the function over a subinterval of [0, 1] as shown in the picture.

We define the variables a and b on all the workers, but let their values depend on labindex so that the intervals [a, b] correspond to the subintervals shown in the figure. We then verify that the intervals are correct. Note that the code in the body of the spmd statement is executed in parallel on all the workers in the parallel pool.

spmd
    a = (labindex - 1)/numlabs;
    b = labindex/numlabs;
    fprintf('Subinterval: [%-4g, %-4g]\n', a, b);
end
Lab  1: 
  Subinterval: [0   , 0.0833333]
Lab  2: 
  Subinterval: [0.0833333, 0.166667]
Lab  3: 
  Subinterval: [0.166667, 0.25]
Lab  4: 
  Subinterval: [0.25, 0.333333]
Lab  5: 
  Subinterval: [0.333333, 0.416667]
Lab  6: 
  Subinterval: [0.416667, 0.5 ]
Lab  7: 
  Subinterval: [0.5 , 0.583333]
Lab  8: 
  Subinterval: [0.583333, 0.666667]
Lab  9: 
  Subinterval: [0.666667, 0.75]
Lab 10: 
  Subinterval: [0.75, 0.833333]
Lab 11: 
  Subinterval: [0.833333, 0.916667]
Lab 12: 
  Subinterval: [0.916667, 1   ]

We let all the workers now use a MATLAB quadrature method to approximate each integral. They all operate on the same function, but on the different subintervals of [0,1] shown in the figure above.

spmd
    myIntegral = integral(@pctdemo_aux_quadpi, a, b);
    fprintf('Subinterval: [%-4g, %-4g]   Integral: %4g\n', ...
            a, b, myIntegral);
end
Lab  1: 
  Subinterval: [0   , 0.0833333]   Integral: 0.332565
Lab  2: 
  Subinterval: [0.0833333, 0.166667]   Integral: 0.32803
Lab  3: 
  Subinterval: [0.166667, 0.25]   Integral: 0.31932
Lab  4: 
  Subinterval: [0.25, 0.333333]   Integral: 0.307088
Lab  5: 
  Subinterval: [0.333333, 0.416667]   Integral: 0.292162
Lab  6: 
  Subinterval: [0.416667, 0.5 ]   Integral: 0.275426
Lab  7: 
  Subinterval: [0.5 , 0.583333]   Integral: 0.257707
Lab  8: 
  Subinterval: [0.583333, 0.666667]   Integral: 0.239713
Lab  9: 
  Subinterval: [0.666667, 0.75]   Integral: 0.221994
Lab 10: 
  Subinterval: [0.75, 0.833333]   Integral: 0.204949
Lab 11: 
  Subinterval: [0.833333, 0.916667]   Integral: 0.188836
Lab 12: 
  Subinterval: [0.916667, 1   ]   Integral: 0.173804

Add the Results

The workers have all calculated their portions of the integral of the function, and we add the results together to form the entire integral over [0, 1]. We use the gplus function to add myIntegral across all the workers and return the sum on all the workers.

spmd
    piApprox = gplus(myIntegral);
end

Inspect Results in the Client

Since the variable piApprox was assigned to inside an spmd statement, it is accessible on the client as a Composite. Composite objects resemble cell arrays with one element for each worker. Indexing into a Composite brings back the corresponding value from the worker to the client.

approx1 = piApprox{1};   % 1st element holds value on worker 1.
fprintf('pi           : %.18f\n', pi);
fprintf('Approximation: %.18f\n', approx1);
fprintf('Error        : %g\n', abs(pi - approx1))
pi           : 3.141592653589793100
Approximation: 3.141592653589792700
Error        : 4.44089e-16
Was this topic helpful?