主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

使用消息传递对 Pi 进行数值估算

此示例展示了使用 spmd 语句的基础知识,以及它们如何提供执行并行计算的交互式方式。我们通过执行相对简单的计算来近似圆周率。

本示例中显示的代码可以在以下函数中找到:

function paralleldemo_quadpi_mpi

简介

我们打算利用

$$ \int_0^1 {4 \over {1 + x^2}} dx = 4(atan(1) - atan(0)) = \pi$$

通过近似左边的积分来近似 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] 子区间内的积分,如图所示。

我们在所有工作单元上定义变量 ab,但让它们的值依赖于 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

另请参阅

|

主题