当你把一个数组分配给一些工作者时,MATLAB®软件将阵列划分为多个段,并将其中的一个段分配给每个工作人员。您可以水平地划分二维数组,将原始数组的列分配给不同的工作人员,也可以垂直地分配行。一个N维的数组可以沿着它的任何一个维进行分区。您可以在数组构造函数命令中指定要对数组的哪个维度进行分区。
例如,要将80×1000个数组分发到四个工人,您可以通过列分区,每个工人为80×250个段,或按行,每个工人获得20×1000个段.如果阵列维度不会均匀地划分工作人员数量,Matlab尽可能均匀地分区。
下面的示例创建一个80 × 1000的复制数组并将其赋值给变量一个
.在这样做时,每个工作者在自己的工作空间中创建一个相同的数组,并将其分配给变量一个
, 在哪里一个
是本地工人。第二个命令分发一个
,创建一个80 × 1000的数组D
这涵盖了所有四名工人。Worker 1存储列1到250,Worker 2存储列251到500,以此类推。默认分布是由最后一个非单例维度决定的,因此,在本例中是一个2维数组。
SPMD A =零(80,1000);d =编码(a)结束实验1:本实验室存储D(:,1:250)。实验室2:此实验室存储D(:,251:500)。实验3:本实验室商店D(:,501:750)。实验室4:此实验室存储D(:,751:1000)。
每个工人都可以访问阵列的所有段。访问本地段的访问速度快于远程段,因为后者需要在工人之间发送和接收数据,因此需要更多时间。
对于每个worker, MATLAB并行命令窗口显示关于协分布数组、局部部分和协分布器的信息。例如,一个8 × 8的单位矩阵在4个工人之间协分布,每个工人有两列,如下所示:
>> SPMD II = EYE(8,'编号')终端实验室1:本实验室商店II(:,1:2)。LocalPart:[8x2 Double] Codistributor:[1x1 CodistRibutor1d] Lab 2:本实验室存储II(:,3:4)。LocalPart:[8x2 Double] Codistributor:[1x1 Codistributor1d] Lab 3:本实验室存储II(:,5:6)。localPart:[8x2 Double]译码器:[1x1 Codistributor1d] Lab 4:本实验室存储II(:,7:8)。localPart:[8x2 Double] Codistributor:[1x1 CodistRibutor1d]
要查看阵列的本地段中的实际数据,请使用getlocalpart.
函数。
在分配数组时N
行,如果N
Matlab的数量均匀地划分,Matlab存储相同的行数(n / numlabs.
)关于每个工人。当此数字由工人数量均匀地默认时,MATLAB尽可能均匀地将数组分区。
MATLAB提供称为CODISTRIBUTOR对象属性尺寸
和划分
您可以使用来确定数组的确切分配。看索引到编码阵列中有关使用协分布数组进行索引的更多信息。
可以分布任何MATLAB内置数据类型的数组,也可以分布复杂或稀疏的数字数组,但不能分布函数句柄或对象类型的数组。
你可以通过以下任何一种方式创建一个codistributed数组:
分区更大的数组- 从所有工人复制的大型数组开始,并将其分区,以便在工人上分发这些部分。当您有足够的内存来存储初始复制数组时,这是最有用的。
从较小的阵列中建造- 从存储在每个工作人员上的较小变体或复制阵列开始,并将它们组合,使得每个阵列成为更大的编码阵列的段。此方法可降低内存要求,因为它允许您从较小的部分构建编码符号。
使用MATLAB构造函数功能-使用任何MATLAB构造函数兰德
要么0
使用CodistRibutor对象参数。这些函数在一步中提供了一种快速构建任何尺寸的编码阵列。
如果您已经在内存中有一个大的数组,您希望Matlab更快地处理,您可以将其分组为更小的段并使用以下所有工人分发这些段codistributed
函数。然后,每个工人都有一个数组,它是原始大小的分数,从而减少访问本地工作者的数据所需的时间。
作为一个简单的例子,以下代码行在分配给变量的每个工作人员上创建一个4×8的复制矩阵一个
:
spmd, A = [11:18;21:28;31:38;41:48],结束A = 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27 28 31 32 33 34 35 36 37 38 41 42 43 44 45 46 47 48
下一行使用codistributed
构建单个4×8矩阵的功能D
沿着阵列的第二维分布:
spmd D = codistribute (A);getLocalPart (D)结束1:本地部分| 2:本地部分| 3:本地部分| 4:本地部分11 12 | 13 14 | 15 16 | 17 18 21日22日| 23日| 24日25日26日| 27 28日31日32 | 33 34 35 36 37 38 41 42 | | | 43 44 45 46 | | 47 48
数组一个
和D
大小相同(4 × 8)。数组一个
存在于每个工人的全部大小,而只有一段阵列D
存在于每个工人身上。
SPMD,尺寸(a),尺寸(d),结束
检查客户端工作空间中的变量,一个数组在工人内部编译spmd
声明,是一种分布式数组,从客户端外面的角度来看spmd
陈述。在SPMD内部不编译的变量,是SPMD外部客户端中的复合材料。
谁名称大小字节A类A 1x4 613 Composite D 4x8 649分布式
看看codistributed
语法和使用信息的功能参考页。
的codistributed
函数对于减少存储数据所需的内存量时,函数尚不太有用,当您首先在一个工作空间中构造完整数组时,然后将其分区为分布式段。要保存在内存中,您可以先在每个工作者上构建较小的碎片(本地部分),然后使用译文
将它们组合成一个分布在工人的单个阵列中。
此示例在四个工作人员中的每一个上创建一个4×250变量数组A,然后使用译文员
要在四个工作人员中分发这些段,请创建一个4×1000个编码阵列。这是变体阵列,一个
:
spmd A = [1:40 0;251:500;501:750;+ 250 * (labindex - 1);WORKER 1 WORKER 2 WORKER 3 1 2…250 | 251 252…500 | 501 502…750 |等251 252…500 | 501 502…750 | 751 752…1000 | etc. 501 502 ... 750 | 751 752 ...1000 | 1001 1002 ...1250 | etc. 751 752 ...1000 | 1001 1002 ...1250 | 1251 1252 ...1500 | etc. | | |
现在将这些段合并成一个数组,该数组由第一个维度(行)分布。数组现在是16乘250,每个worker上都有一个4乘250的段:
SPMD D = CODISTRIBUTED.BUILD(A,CODISTRIBUTOR1D(1,[4 4 4 4],[16 250]))END LAB 1:本实验室存储D(1:4,:)。localPart:[4x250双]译码器:[1x1 Codistributor1d] WhoS名称大小字节A类1x4 613复合D 16x250 649分布式
如果您想创建一个编码阵列,您也可以使用同一时尚的复制数组,该数组段均始终相同。看看codistributed
语法和使用信息的功能参考页。
MATLAB提供了几个数组构造函数,您可以用于构建特定值,大小和类的编码阵列。这些函数以与matlab语言中的非启动对手相同的方式操作,除了它们使用指定的Codistributor对象将结果数组分发,编号人员
.
构造函数功能。这里列出了协作分布的构造函数。使用编号人员
参数(由此创建译文员
功能:代码= Codistributor()
)指定要分发数组的维度。有关这些函数的个人参考页,请参阅以下语法和使用信息。
眼睛
(___,代码学家)错误的
(___,代码学家)INF.
(___,代码学家)南
(___,代码学家)那些
(___,代码学家)兰德
(___,代码学家)兰迪
(___,代码学家)兰德
(___,代码学家)真的
(___,代码学家)0
(___,代码学家)CodistRibuted.cell.
(m,n,...,copist)codistributed.colon
(a,d,b)编码。Linspace.
(m,n,...,译码家)编码。logspace.
(m,n,...,copist)稀疏的
(m,n,代码师)编号.Speye.
(m,...,代码师)CodistRibuted.Sprand.
(m, n,密度,codist)CodistRibuted.Sprandn.
(m, n,密度,codist)
驻留在每个工作人员上的编码阵列的那部分是一个更大的阵列。每个工作人员都可以在其自己的段段上工作,或者它可以在自己的变体或私有数组中制作该段的副本。该编码阵列段的本地副本称为a本地阵列.
的getlocalpart.
函数将编码阵列的段复制到单独的变体阵列。此示例使本地副本l
每个编码阵列的段D
.的大小l
表明它只包含本地部分D
每个工人。假设您将跨四个工人分发数组:
SPMD(4)A = [1:80;81:160;161:240];d =编码(a);尺寸(d)l = getlocalpart(d);尺寸(l)结束
每个工人的回报:
3 80 3 20
每个工作人员都能识别出协作分布的数组D
是3×80。但请注意,本地部分的大小,l
,每个工人是3乘20,因为80列D
分发超过四名工人。
使用译文
功能要执行反向操作。这个功能,描述于从较小的阵列中建造,将局部变量阵列组合成沿指定维度分布的单个阵列。
继续前面的示例,占据局部变体阵列l
并将它们放在一起作为段构建一个新的编码阵列X
.
SPMD编码子= CodistRibutor1d(2,[20 20 20],[3 80]);x =译码.Build(L,译码者);尺寸(x)结束
每个工人的回报:
3 80.
MATLAB提供了多种功能,可提供有关任何特定阵列的信息。除了这些标准函数之外,还有两个功能,可仅用编码阵列。
的iscodistreibuted
函数返回逻辑1
(真的
)如果输入数组是编码的,并且逻辑0
(错误的
) 否则。语法是
SPMD,TF = IscodistRibuted(D),结束
在哪里D
是任何matlab阵列。
CodistRibutor对象确定数组如何分区以及其分发的维度。要访问数组的编码器,请使用getododistributor.
函数。这返回两个属性,尺寸
和划分
:
SPMD,GetoDoDistributor(x),终点:2分区:[20 20 20]
的尺寸
的价值2
表示阵列X
按列分布(维度2);和划分
的价值[20 20 20 20]
意味着二十列驻留在四个工人中的每一个。
要以编程方式获取这些属性,请返回输出getododistributor.
到一个变量,然后使用点表示法访问每个属性:
spmd c = getcodistributor(x);部分= C.Partition Dim = C.dimensile结束
提供有关标准阵列的信息的其他功能也适用于编码阵列并使用相同的语法。
构造数组时,您可以沿着阵列的尺寸分发数组的部件。您可以使用该阵列在现有数组上更改此分发的方向重新分配
使用不同的Codistributor对象的函数。
构造一个8×16的编码阵列D
四个工人上列分发的随机值:
SPMD D = RAND(8,16,Codistributor());尺寸(getlocalpart(d))结束
每个工人的回报:
8 4.
创建一个从已分发列已分发的现有的行分发的新的编码阵列:
SPMD X =重新分配(D,CodistRibutor1d(1));尺寸(getlocalpart(x))结束
每个工人的回报:
2 16
您可以使用恢复编码的数组来使用其未分配的表单收集
函数。收集
获取驻留在不同工作者上的数组的段,并将它们组合成所有工人的复制数组,或者在一个工人上进入单个数组。
沿第二维分发4×10阵列至四名工人:
SPMD,A = [11:20;21:30;31:40;41:50],结束A = 11 12 13 14 15 16 17 18 19 20 21 22 23 22 32 32 32 32 32 32 32 32 33 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 3234 32 43 42 40 43 49 45 49 50 SPMD,d =编码(a),最终工作人员1工人2工人3工人4 11 12 13 |14 15 16 |17 18 |19 20 21 22 23 |24 25 26 |27 28 | 29 30 31 32 33 | 34 35 36 | 37 38 | 39 40 41 42 43 | 44 45 46 | 47 48 | 49 50 | | | spmd, size(getLocalPart(D)), end Lab 1: 4 3 Lab 2: 4 3 Lab 3: 4 2 Lab 4: 4 2
通过收集片段,将未分布的片段恢复到完整的数组形式:
SPMD,X =收集(d),端X = 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 4849 50 SPMD,尺寸(X),结束4 10
虽然索引成一个非识别的阵列相当简单,但是汇编阵列需要额外的考虑因素。非识别阵列的每个维度在1到最终下标的范围内索引,该下标在Matlab中表示结束
关键字。任何尺寸的长度都可以很容易地使用大小
要么长度
函数。
通过编码阵列,不容易获得这些值。例如,阵列的第二段(驻留在Worker 2的工作空间中)的起始索引取决于阵列分布。对于一个200×1000个阵列,具有四个工人的列默认分发,工作人员2的起始索引为251.对于1000×200阵列,也可以被列分发,同一索引将为51。至于结束指数,这不是通过使用的结束
关键字,结束
在本例中是指整个数组的结尾;也就是最后一段的最后一个下标。每个线段的长度也不是用长度
要么大小
函数,因为它们只返回整个阵列的长度。
matlab.冒号
运营商和结束
关键字是索引非分布式数组的两个基本工具。对于共分布数组,MATLAB提供了一个版本的冒号
操作员称为codistributed.colon
.这实际上是一个函数,而不是符号运算符冒号
.
请注意
使用数组索引到编码阵列中时,您只能仅使用复制或编码阵列进行索引。工具箱不检查以确保复制索引,因为这将需要全局通信。因此,使用不受支持的变体(如金宝applabindex
)索引到编码阵列可能会产生意外结果。
假设您有100万个元素的行向量,分布在几个工人中,并且您希望找到其元素编号225,000。也就是说,您想知道Worker包含此元素的工作,以及该工作者的载体的本地部分的位置。的GlobalIndices.
函数提供了编码阵列的本地和全局索引之间的相关性。
d = rand(1,1e6,'分布');%由列SPMD GlobalInd = GlobalIndices(D,2)分发;pos = find(globalind == 225e3);如果〜isempty(pos)fprintf(...'元素位于Worker%d的位置%d。\ n',pos,labindex);结束
如果您在四个工人的池中运行此代码,则获得此结果:
Lab 1:元素在工人1上位于225000位置。
如果你在一个有5个工人的池中运行这段代码,你会得到这样的结果:
实验2:元件在工人2的25000位置。
注意如果使用不同大小的池,则元素将在不同的工作人员的不同位置结束,但可以使用相同的代码来定位元素。
作为通过行或列的单个维度分发的替代方案,您可以使用块分发矩阵'2dbc'
或二维块循环分布。代替包括矩阵的多个完整行或列的段,编码阵列的片段是二维方块。
例如,考虑具有升序元素值的简单8×8矩阵。您可以在一个中创建此数组spmd
声明或沟通工作。
SPMD A = RESHAPE(1:64,8,8)结束
结果是复制数组:
1 9 17 25 33 41 49 57 2 10 18 26 34 40 58 3 11 11 19 23 32 54 52 60 5 13 2 2 23 45 53 61 6 13 22 30 34 45 53 61 6 13 22 30 38 46 54 62 62 7 1523 31 39 47 55 63 8 16 24 32 40 48 56 64
假设您要在四个工人之间分发此数组,其中4×4块作为每个工作人员的本地部分。在这种情况下,实验室网格是工人的2×2布置,块尺寸是侧面上四个元件的平方(即,每个块是4×4平方)。使用此信息,您可以定义CodistRibutor对象:
spmd DIST = codistributor2dbc([2 2], 4);结束
现在,您可以使用此编码器对象分发原始矩阵:
SPMD AA =编码(A,DIST)结束
这根据本计划分配工人中的阵列:
如果实验网格没有完全覆盖编码阵列的尺寸,则仍然可以使用'2dbc'
分布,即块循环。在这种情况下,您可以想象实验网格在两个尺寸中重复覆盖,直到包括所有原始矩阵元素。
使用相同的原始8×8矩阵和2×2实验网格,考虑块大小为3而不是4,因此在工人之间分配3×3平方块。代码如下所示:
SPMD DIST = CODISTRIBUTOR2DBC([2 2],3)AA =编码(A,DIST)结束
实验网格的第一行是分配给工人1和工人2的,但它只包含原始矩阵的八列中的六列。因此,接下来的两列分配给worker 1。这个过程将继续进行,直到第一行中的所有列都被分布。然后一个类似的过程适用于行,当你继续进行矩阵,如下所示的分布方案:
上图示出了需要4个实验网格覆盖以容纳整个原始矩阵的方案。以下代码显示了每个工人的数据分发。
spmd getLocalPart (AA)结束
LAB 1:ANS = 1 9 17 49 57 2 10 18 50 58 3 11 19 51 59 7 15 23 50 63 8 16 24 56 64 LAB 2:ans = 25 33 41 26 34 42 27 32 40 40 40 40 48LAB 3:ANS = 4 12 20 52 60 5 13 21 53 61 6 14 22 54 62 LAB 4:ans = 28 36 44 29 37 45 30 38 46
以下几点值得注意:
'2dbc'
除非块大小至少几十几,否则分发可能无法提供任何性能增强。默认块大小为64。
实验网格应尽可能接近正方形。
并非所有提高工作的功能'1D'
编码阵列工作'2dbc'
编号阵列。