使用消息传递对 Pi 进行数值估算
此示例展示了使用 spmd 语句的基础知识,以及它们如何提供执行并行计算的交互式方式。我们通过执行相对简单的计算来近似圆周率。
本示例中显示的代码可以在以下函数中找到:
function paralleldemo_quadpi_mpi
简介
我们打算利用

通过近似左边的积分来近似 pi。
我们打算让并行池并行执行计算,并使用 spmd 关键字来标记并行代码块。我们首先看一下当前打开的并行池的大小。
p = gcp; p.NumWorkers
Starting parallel pool (parpool) using the 'Processes' profile ...
Connected to the parallel pool (number of workers: 6).
ans =
6
并行计算
我们通过从 0 到 1 的 4/(1 + x^2) 的数值积分来近似 pi。
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);
我们将工作分配给工作单元,让每个工作单元计算函数在 [0, 1] 子区间内的积分,如图所示。

我们在所有工作单元上定义变量 a 和 b,但让它们的值依赖于 spmdIndex,以便区间[a,b]对应于图中所示的子区间。然后我们验证间隔是否正确。请注意,spmd 语句主体中的代码在并行池中的所有工作单元上并行执行。
spmd a = (spmdIndex - 1)/spmdSize; b = spmdIndex/spmdSize; fprintf('Subinterval: [%-4g, %-4g]\n', a, b); end
我们现在让所有工作单元使用 MATLAB 求积法来近似每个积分。它们都对相同的函数进行操作,但是对上图所示的 [0,1] 的不同子区间进行操作。
spmd myIntegral = integral(@pctdemo_aux_quadpi, a, b); fprintf('Subinterval: [%-4g, %-4g] Integral: %4g\n', ... a, b, myIntegral); end
添加结果
工作单元都计算出了各自在函数上的积分部分,我们将结果相加,得到 [0, 1] 上的整个积分。我们使用 spmdPlus 函数将 myIntegral 添加到所有工作单元身上,并返回所有工作单元的总和。
spmd piApprox = spmdPlus(myIntegral); end
在客户端检查结果
由于变量 piApprox 被分配给 spmd 语句内部,因此它可以作为 Composite 在客户端进行访问。Composite 对象类似于元胞数组,每个工作单元对应一个元素。对 Composite 进行索引会将相应的值从工作单元带回给客户端。
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.141592653589793116 Approximation: 3.141592653589793116 Error : 0