将数组分发给并行工作单元
使用分布式数组在各个工作单元之间划分数据
根据数据在内存中的适应情况,选择以下方法之一:
如果您的数据当前位于本地计算机的内存中,则可以使用
distributed函数将现有数组从客户端工作区分发到并行池的工作单元。此选项对于测试或在执行显著增加数组大小的操作之前很有用,例如repmat。如果您的数据不适合本地计算机的内存,但适合集群的内存,则可以使用
datastore与distributed函数将数据读入并行池工作单元的内存中。如果您的数据不适合集群内存,您可以使用带
tall数组的datastore对数据进行分区处理。另请参阅使用 tall 数组和数据存储的大数据工作流。
使用 datastore 并行加载分布式数组
如果您的数据无法容纳在本地计算机的内存中,但可以容纳在集群的内存中,那么您可以使用 datastore 与 distributed 函数来创建分布式数组,并在您的工作单元之间划分数据。
此示例显示如何使用 datastore 创建和加载分布式数组。使用航空公司航班数据的表格文件创建数据存储。该数据集太小,无法显示对各个工作单元进行平等分区的情况。为了仿真大型数据集,可以使用 repmat 人为地增加数据存储的大小。
files = repmat({'airlinesmall.csv'}, 10, 1);
ds = tabularTextDatastore(files);
选择示例变量。
ds.SelectedVariableNames = {'DepTime','DepDelay'};
ds.TreatAsMissing = 'NA';
通过并行读取数据存储来创建分布式表。对数据存储进行分区,每个工作单元一个分区。然后每个工作单元从相应的分区读取所有数据。这些文件必须位于工作单元可以访问的共享位置。
dt = distributed(ds);
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
显示有关分布式表的摘要信息。
summary(dt)
Variables:
DepTime: 1,235,230×1 double
Values:
min 1
max 2505
NaNs 23,510
DepDelay: 1,235,230×1 double
Values:
min -1036
max 1438
NaNs 23,510
确定 tall 表的大小。
size(dt)
ans =
1235230 2
返回 dt 的前几行。
head(dt)
ans =
DepTime DepDelay
_______ ________
642 12
1021 1
2055 20
1332 12
629 -1
1446 63
928 -2
859 -1
1833 3
1041 1
最后,检查每个工作单元加载了多少数据。
spmd, dt, end
Worker 1:
This worker stores dt2(1:370569,:).
LocalPart: [370569×2 table]
Codistributor: [1×1 codistributor1d]
Worker 2:
This worker stores dt2(370570:617615,:).
LocalPart: [247046×2 table]
Codistributor: [1×1 codistributor1d]
Worker 3:
This worker stores dt2(617616:988184,:).
LocalPart: [370569×2 table]
Codistributor: [1×1 codistributor1d]
Worker 4:
This worker stores dt2(988185:1235230,:).
LocalPart: [247046×2 table]
Codistributor: [1×1 codistributor1d]请注意,数据在各个工作单元之间是平均划分的。有关 datastore 的更多详细信息,请参阅 什么是数据存储?
有关大数据工作流的更多详细信息,请参阅选择并行计算解决方案。
创建分布式和共存分布式数组的替代方法
如果您的数据适合您的本地计算机的内存,则可以使用分布式数组在您的工作单元之间划分数据。使用 distributed 函数在 MATLAB® 客户端中创建一个分布式数组,并将数据存储在打开的并行池的工作单元中。分布式数组在一个维度上分布,并且在整个工作单元中沿着这个维度尽可能均匀地分布。创建分布式数组时,您无法控制分布的细节。
您可以通过多种方式创建分布式数组:
前两种技术不涉及使用 spmd 创建数组,但可以使用 spmd 来操作以这种方式创建的数组。例如:
在客户端工作区创建一个数组,然后使其成为分布式数组。
parpool('Processes',2) % Create pool W = ones(6,6); W = distributed(W); % Distribute to the workers spmd T = W*2; % Calculation performed on workers, in parallel. % T and W are both codistributed arrays here. end T % View results in client. whos % T and W are both distributed arrays here. delete(gcp) % Stop pool
或者,您可以使用 codistributed 函数,它允许您控制更多选项,例如维度和分区,但通常更复杂。您可以通过在工作单元本身上执行来创建 codistributed 数组,可以在 spmd 语句内或通信作业内执行。创建 codistributed 数组时,您可以控制分布的各个方面,包括维度和分区。
分布式和共存分布式数组之间的关系是一种视角关系。共存分布式数组将分区到各个工作单元上,您可以通过这些工作单元执行代码来创建或操作它们。当您在客户端中创建一个分布式数组时,您可以在 spmd 语句内将其作为共存分布式数组进行访问。当您在 spmd 语句中创建一个共存分布式数组时,您可以在客户端中将其作为分布式数组进行访问。只有 spmd 语句允许您从两个不同的角度访问相同的数组数据。
您可以通过多种方式创建 codistributed 数组:
在
spmd语句或通信作业中使用codistributed函数来共同分配运行该作业的工作单元上已存在的数据。使用任意一个共存分布式函数直接在工作单元上构建一个共存分布式数组。这种技术并不要求数组已经存在于工作单元中。函数包括
和eye(___,'codistributed')。有关完整列表,请参阅rand(___,'codistributed')codistributed对象参考页面。在
spmd语句外创建一个分布式数组,然后在同一并行池上运行的spmd语句内将其作为共存分布式数组进行访问。
使用非默认分布方案在 spmd 语句内创建一个共存分布式数组。首先,沿第三个维度定义一维分布,其中工作单元 1 有 4 个部分,工作单元 2 有 12 个部分。然后创建一个 3×3×16 的零数组。
parpool('Processes',2) % Create pool spmd codist = codistributor1d(3,[4,12]); Z = zeros(3,3,16,codist); Z = Z + spmdIndex; end Z % View results in client. % Z is a distributed array here. delete(gcp) % Stop pool
有关共存分布式数组的更多详细信息,请参阅 使用共存分布式数组。
另请参阅
distributed | codistributed | tall | datastore | spmd | repmat | eye | rand