主要内容

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

使用 spmdReduce 实现 MPI_Allreduce 功能

在这个示例中,我们研究 spmdReduce 函数及其构建的函数:spmdPlusspmdCat。这些看似简单的函数实际上是并行编程中非常强大的工具。

spmdReduce 函数允许我们对所有工作单元上定义的变量执行任何关联二元运算。这样,我们不仅可以对所有工作单元的变量求和,还可以在所有工作单元中找到它的最小值和最大值,将它们连接起来,并执行许多其他有用的操作。

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

function paralleltutorial_gop

简介

在进行并行编程时,我们经常会遇到在所有工作单元上定义一个变量的情况,并且我们想要对所有工作单元上存在的变量执行操作。例如,如果我们输入 spmd 语句并定义

spmd
    x = spmdIndex;
end

对于所有工作单元,我们可能想要计算所有工作单元的 x 值的总和。这正是 spmdPlus 操作所做的,它对各个工作单元 的 x 求和,并将结果复制到所有工作单元上:

spmd
    s = spmdPlus(x);
end

Spmd 语句内部分配的变量在客户端上表示为 Composite。我们可以通过对 Composite 进行索引,将工作单元得到的结果值传送给客户端,就像对元胞数组进行索引一样:

s{1} % Display the value of s on worker 1.  All workers store the same value.
ans =

    21

此外,spmdReducespmdPlusspmdCat 允许我们指定应返回函数输出的单个工作单元,并且它们对其他工作单元返回一个空向量。

spmd
    s = spmdPlus(x, 1);
end
s{1}
ans =

    21

此示例展示了如何在所有工作单元中执行主机类似于加法的操作。在 MPI 中,这些被称为集体操作,例如 MPI_SUM、MPI_PROD、MPI_MIN、MPI_MAX 等。

为我们的示例创建输入数据

我们在所有示例中使用的数据都非常简单:一个 1×2 的变体数组,它只比我们一开始定义的 x 稍微复杂一点:

spmd
    x = spmdIndex + (1:2)
end

使用 spmdPlusspmdCat

现在,我们已将向量 x 初始化为各个工作单元上的不同值,我们可以提出一些问题,例如各个工作单元进程上的 x 的每个元素的值之和是多少?那么乘积、最小值和最大值又如何呢?正如我们介绍的那样,

spmd
    s = spmdPlus(x);
end
s{1}
ans =

    27    33

返回 x 的值的逐元素的加法。然而,spmdPlus 只是 spmdReduce 运算的一个特例。spmdReduce 函数允许我们对变体数组的元素执行跨工作单元的任何关联操作。结合运算的最基本示例是加法;它具有结合性,因为加法与所使用的分组无关:

(a + b) + c = a + (b + c)

在 MATLAB® 中,加法可以用 @plus 函数句柄表示,因此我们也可以将 spmdPlus(x) 写为

spmd
    s = spmdReduce(@plus, x);
end
s{1}
ans =

    27    33

我们可以使用 x 函数在各个工作单元之间连接向量 spmdCat,并且可以选择要连接的维度。

spmd
    y1 = spmdCat(x, 1); % Concatenate along rows.
    y2 = spmdCat(x, 2); % Concatenate along columns.
end
y1{1}
y2{1}
ans =

     2     3
     3     4
     4     5
     5     6
     6     7
     7     8


ans =

     2     3     3     4     4     5     5     6     6     7     7     8

spmdReduce 的其他基本用途

计算各个工作单元的 x 值的逐元素乘积很简单:

spmd
    p = spmdReduce(@times, x);
end
p{1}
ans =

        5040       20160

我们还可以找到所有工作单元中 x 的逐元素最大值:

spmd
    M = spmdReduce(@max, x);
    m = spmdReduce(@min, x);
end
M{1}
m{1}
ans =

     7     8


ans =

     2     3

逻辑运算

MATLAB 有更多内置的结合运算。逻辑 AND、OR 和 XOR 运算由 @and@or@xor 函数句柄表示。例如,查看逻辑数组

spmd
    y = (x > 4)
end

然后我们可以轻松地在各个工作单元上对 y 的元素执行以下逻辑运算:

spmd
    yand = spmdReduce(@and, y);
    yor = spmdReduce(@or, y);
    yxor = spmdReduce(@xor, y);
end
yand{1}
yor{1}
yxor{1}
ans =

  1×2 logical array

   0   0


ans =

  1×2 logical array

   1   1


ans =

  1×2 logical array

   1   0

按位运算

为了结束我们对 MATLAB 内置的结合运算的介绍,我们来看一下按位 AND、OR 和 XOR 运算。这些由 @bitand@bitor@bitxor 函数句柄表示。

spmd
    xbitand = spmdReduce(@bitand, x);
    xbitor = spmdReduce(@bitor, x);
    xbitxor = spmdReduce(@bitxor,  x);
end
xbitand{1}
xbitor{1}
xbitxor{1}
ans =

     0     0


ans =

     7    15


ans =

     1    11

查找最小值和最大值的位置

我们只需进行一点点编程就可以找到与各个工作单元中逐元素的 spmdIndex 最大值相对应的 x。我们只需几行代码就可以做到这一点:

type pctdemo_aux_gop_maxloc
function [val, loc] = pctdemo_aux_gop_maxloc(inval)
%PCTDEMO_AUX_GOP_MAXLOC Find maximum value of a variant and its spmdIndex.
%   [val, loc] = pctdemo_aux_gop_maxloc(inval) returns to val the maximum value
%   of inval across all workers.  The spmdIndex where this maximum value
%   resides is returned to loc.

%   Copyright 2007 The MathWorks, Inc.

    out = spmdReduce(@iMaxLoc, {inval, spmdIndex*ones(size(inval))});
    val = out{1};
    loc = out{2};
end

function out = iMaxLoc(in1, in2)
% Calculate the max values and their locations.  Return them as a cell array.
    in1Largest = (in1{1} >= in2{1});
    maxVal = in1{1};
    maxVal(~in1Largest) = in2{1}(~in1Largest);
    maxLoc = in1{2};
    maxLoc(~in1Largest) = in2{2}(~in1Largest);
    out = {maxVal, maxLoc};
end

当该函数被实现后,它可以像任何内置操作一样轻松地应用:

spmd
    [maxval, maxloc] = pctdemo_aux_gop_maxloc(x);
end
[maxval{1}, maxloc{1}]
ans =

     7     8     6     6

类似地,我们只需要几行代码就可以找到 spmdIndex,其中 x 在所有工作单元中逐元素最小值出现的位置:

type pctdemo_aux_gop_minloc
function [val, loc] = pctdemo_aux_gop_minloc(inval)
%PCTDEMO_AUX_GOP_MINLOC Find minimum value of a variant and its spmdIndex.
%   [val, loc] = pctdemo_aux_gop_minloc(inval) returns to val the minimum value
%   of inval across all workers.  The spmdIndex where this minimum value
%   resides is returned to loc.

%   Copyright 2007 The MathWorks, Inc.

    out = spmdReduce(@iMinLoc, {inval, spmdIndex*ones(size(inval))});
    val = out{1};
    loc = out{2};
end

function out = iMinLoc(in1, in2)
% Calculate the min values and their locations.  Return them as a cell array.
    in1Smallest = (in1{1} < in2{1});
    minVal = in1{1};
    minVal(~in1Smallest) = in2{1}(~in1Smallest);
    minLoc = in1{2};
    minLoc(~in1Smallest) = in2{2}(~in1Smallest);
    out = {minVal, minLoc};
end

然后我们可以轻松地用 spmdReduce 找到最小值:

spmd
    [minval, minloc] = pctdemo_aux_gop_minloc(x);
end
[minval{1}, minloc{1}]
ans =

     2     3     1     1

另请参阅

| | |

主题