Chapel 中分散子阵列的高效收集和传输
Efficient collection and transfer of scattered sub-arrays in Chapel
最近,我偶然发现了Chapel。我喜欢教程中给出的示例,但其中许多在我眼中是平行的,令人尴尬。我正在研究多体量子物理学中的散射问题,一个常见问题可以简化为以下内容。
- 形状
M x N x N
的张量A
填充了M
个不同参数[=13]的矩阵方程的解=]
- 需要张量的子集
A
来计算校正项
每个参数 1..M
.
问题的第一部分令人尴尬地并行。
因此,我的问题是是否以及如何仅将张量 A
的所需子集传输到集群的每个区域并最小化必要的沟通?
当 Chapel 正常工作时,应该以高效的方式执行分布式数组和本地数组(比方说)之间的数组切片传输。这意味着您应该能够使用 Chapel 的数组切片符号来编写此类张量子集传输。
例如,下面是编写这种模式的一种方法:
// define a domain describing a 5 x 7 x 3 index set anchored at index (x,y,z)
const Slice = {x..#5, y..#7, z..#3};
// create a new array variable that stores the elements from distributed array
// `myDistArray` locally
var myLocalArray = myDistArray[Slice];
新变量 myLocalArray
将是一个数组,其元素是 myDistArray
中元素的副本,如 Slice
中的索引所述。 myLocalArray
的域将是切片域 Slice
,因此由于 Slice
是一个非分布式域,因此 myLocalArray
也将是一个本地/非分布式数组,并且因此,当从当前区域设置操作时,不会产生使用 Chapel 的分布式数组表示法的任何开销。
迄今为止,我们主要关注为块分布式数组优化此类传输。例如,对于像上面例子这样的情况,当 myDistArray 是块分布式时,我看到区域设置之间的通信数量是固定的,因为我改变了切片的大小(尽管这些通信的大小显然会根据需要传输的元素数量)。已知其他案例和模式需要更多优化工作,因此如果您发现案例未按预期执行/扩展,请针对它提交 Chapel GitHub issue 以帮助提醒我们您的需求 and/or 帮助您找到解决方法。
所以,勾画出你描述的模式,我可能会想象做这样的事情:
// create a local and distributed version of the complete tensor space
const LocTensorSpace = {1..M, 1..N, 1..N},
TensorSpace = LocTensorSpace dmapped Block(LocTensorSpace);
// declare array A to store the result of step 1
var A: [TensorSpace] real;
// ...compute A here...
// declare a 1D distributed form of the parameter space to drive step 2
const ParameterSpace = {1..M} dmapped Block({1..M});
// loop over the distributed parameter space; each locale will use all its cores
// to compute on its subset of {1..M} in parallel
forall m in ParameterSpace {
// create a local domain to describe the indices you want from A
const TensorSlice = { /* ...whatever indices you need here... */ };
// copy those elements into a local array
var locTensor = A[TensorSlice];
// ...compute on locTensor here...
}
其他一些似乎与我相关但我不想让这个问题陷入困境的事情是:
- 如果需要,可以声明 TensorSpace / A,这样只有 1..M 维度分布在各个区域,{1..N, 1..N} 平面是局部的
- 还有一些方法可以查询语言环境拥有分布式数组的哪些索引;结合上一点,这可能是一种减少所需通信量的方法,假设步骤 2 的迭代与 A
的平面之间存在对应关系
- 还有一些方法可以就地引用分布式数组切片 and/or 以给它一个符号名称,而不是像上面建议的那样创建它的本地副本
- 如果 desired/preferred A 可以声明为二维数组的一维分布式数组,但如果您想访问 space
的 3D 切片,这可能不太好
(如果您对此感兴趣,请随时提出后续问题)
最后,为了后代,这是我在将此响应放在一起时编写的程序,以确保我在通信数量和获取本地数组方面得到预期的行为(这与 chpl version 1.23.0 pre-release (ad097333b1)
一起使用,但我希望最近发布的 Chapel 会出现相同的行为:
use BlockDist, CommDiagnostics;
config const M = 10, N=20;
const LocTensorSpace = {1..M, 1..N, 1..N},
TensorSpace = LocTensorSpace dmapped Block(LocTensorSpace);
var A: [TensorSpace] real;
forall (i,j,k) in TensorSpace do
A[i,j,k] = i + j / 100.0 + k / 100000.0;
config const xs = 5, ys = 7, zs = 3, // size of slice
x = M/2-xs/2, y = N/2-ys/2, z = N/2-zs/2; // origin of slice
const Slice = {x..#xs, y..#ys, z..#zs};
writeln("Copying a ", (xs,ys,zs), " slice of A from ", (x,y,z));
resetCommDiagnostics();
startCommDiagnostics();
var myLocArr = A[Slice];
stopCommDiagnostics();
writeln(getCommDiagnostics());
writeln(myLocArr);
writeln(myLocArr.isDefaultRectangular());
最近,我偶然发现了Chapel。我喜欢教程中给出的示例,但其中许多在我眼中是平行的,令人尴尬。我正在研究多体量子物理学中的散射问题,一个常见问题可以简化为以下内容。
- 形状
M x N x N
的张量A
填充了M
个不同参数[=13]的矩阵方程的解=] - 需要张量的子集
A
来计算校正项 每个参数1..M
.
问题的第一部分令人尴尬地并行。
因此,我的问题是是否以及如何仅将张量 A
的所需子集传输到集群的每个区域并最小化必要的沟通?
当 Chapel 正常工作时,应该以高效的方式执行分布式数组和本地数组(比方说)之间的数组切片传输。这意味着您应该能够使用 Chapel 的数组切片符号来编写此类张量子集传输。
例如,下面是编写这种模式的一种方法:
// define a domain describing a 5 x 7 x 3 index set anchored at index (x,y,z)
const Slice = {x..#5, y..#7, z..#3};
// create a new array variable that stores the elements from distributed array
// `myDistArray` locally
var myLocalArray = myDistArray[Slice];
新变量 myLocalArray
将是一个数组,其元素是 myDistArray
中元素的副本,如 Slice
中的索引所述。 myLocalArray
的域将是切片域 Slice
,因此由于 Slice
是一个非分布式域,因此 myLocalArray
也将是一个本地/非分布式数组,并且因此,当从当前区域设置操作时,不会产生使用 Chapel 的分布式数组表示法的任何开销。
迄今为止,我们主要关注为块分布式数组优化此类传输。例如,对于像上面例子这样的情况,当 myDistArray 是块分布式时,我看到区域设置之间的通信数量是固定的,因为我改变了切片的大小(尽管这些通信的大小显然会根据需要传输的元素数量)。已知其他案例和模式需要更多优化工作,因此如果您发现案例未按预期执行/扩展,请针对它提交 Chapel GitHub issue 以帮助提醒我们您的需求 and/or 帮助您找到解决方法。
所以,勾画出你描述的模式,我可能会想象做这样的事情:
// create a local and distributed version of the complete tensor space
const LocTensorSpace = {1..M, 1..N, 1..N},
TensorSpace = LocTensorSpace dmapped Block(LocTensorSpace);
// declare array A to store the result of step 1
var A: [TensorSpace] real;
// ...compute A here...
// declare a 1D distributed form of the parameter space to drive step 2
const ParameterSpace = {1..M} dmapped Block({1..M});
// loop over the distributed parameter space; each locale will use all its cores
// to compute on its subset of {1..M} in parallel
forall m in ParameterSpace {
// create a local domain to describe the indices you want from A
const TensorSlice = { /* ...whatever indices you need here... */ };
// copy those elements into a local array
var locTensor = A[TensorSlice];
// ...compute on locTensor here...
}
其他一些似乎与我相关但我不想让这个问题陷入困境的事情是:
- 如果需要,可以声明 TensorSpace / A,这样只有 1..M 维度分布在各个区域,{1..N, 1..N} 平面是局部的
- 还有一些方法可以查询语言环境拥有分布式数组的哪些索引;结合上一点,这可能是一种减少所需通信量的方法,假设步骤 2 的迭代与 A 的平面之间存在对应关系
- 还有一些方法可以就地引用分布式数组切片 and/or 以给它一个符号名称,而不是像上面建议的那样创建它的本地副本
- 如果 desired/preferred A 可以声明为二维数组的一维分布式数组,但如果您想访问 space 的 3D 切片,这可能不太好
(如果您对此感兴趣,请随时提出后续问题)
最后,为了后代,这是我在将此响应放在一起时编写的程序,以确保我在通信数量和获取本地数组方面得到预期的行为(这与 chpl version 1.23.0 pre-release (ad097333b1)
一起使用,但我希望最近发布的 Chapel 会出现相同的行为:
use BlockDist, CommDiagnostics;
config const M = 10, N=20;
const LocTensorSpace = {1..M, 1..N, 1..N},
TensorSpace = LocTensorSpace dmapped Block(LocTensorSpace);
var A: [TensorSpace] real;
forall (i,j,k) in TensorSpace do
A[i,j,k] = i + j / 100.0 + k / 100000.0;
config const xs = 5, ys = 7, zs = 3, // size of slice
x = M/2-xs/2, y = N/2-ys/2, z = N/2-zs/2; // origin of slice
const Slice = {x..#xs, y..#ys, z..#zs};
writeln("Copying a ", (xs,ys,zs), " slice of A from ", (x,y,z));
resetCommDiagnostics();
startCommDiagnostics();
var myLocArr = A[Slice];
stopCommDiagnostics();
writeln(getCommDiagnostics());
writeln(myLocArr);
writeln(myLocArr.isDefaultRectangular());