这在我的笔记本电脑上运行良好,但我想知道这是否会导致大规模问题。假设我想填充一个非常大的数组,但每个条目都需要对一个大的、稀疏的分布式矩阵进行密集的矩阵运算。我应该期望以下设计能够坚持吗?
var x: [1..N] real;
forall i in [1..N] {
x[i] = reallyHeavyMatrixComputation(i);
}
有保持这种理智的提示吗?我应该使用 admapped
的域x
还是什么?
这在我的笔记本电脑上运行良好,但我想知道这是否会导致大规模问题。假设我想填充一个非常大的数组,但每个条目都需要对一个大的、稀疏的分布式矩阵进行密集的矩阵运算。我应该期望以下设计能够坚持吗?
var x: [1..N] real;
forall i in [1..N] {
x[i] = reallyHeavyMatrixComputation(i);
}
有保持这种理智的提示吗?我应该使用 admapped
的域x
还是什么?
Chapel 的 forall 循环可以扩展到多个语言环境,但它们是否会这样做取决于它们迭代的内容以及循环的主体。
更详细地说,关键的并行循环策略,例如“应该使用多少个任务?” 和“这些任务应该在哪里运行?” 由循环的迭代控制。例如,在以下循环中:
var x: [1..N] real; // declare a local array
forall i in 1..N do // iterate over its indices in parallel
x[i] = reallyHeavyMatrixComputation(i);
循环的 iterand 是 range 1..N
。默认情况下,范围的迭代器将创建与当前语言环境中的处理器单元/内核数相等的本地任务数。因此,上面的循环不会随着使用更多语言环境而变得更快,除非reallyHeavyMatrixComputation()
它本身包含以智能方式在语言环境中分布计算的 on 子句。如果它根本不包含任何 on 子句,则计算将永远不会离开 locale #0,并且只会是共享内存。
相反,如果使用 forall 循环在分布式域或数组上进行迭代,默认策略通常是在每个目标区域设置上运行的任务数量等于以“所有者计算”方式在该区域设置上的处理器内核数量. 也就是说,每个语言环境将执行它所拥有的迭代子集,由分布确定。例如,给定循环:
use CyclicDist; // make use of the cyclic distribution module
var D = {1..N} dmapped Cyclic(startIdx=1); // declare a cyclically distributed domain
var x: [D] real; // declare an array over that domain
forall i in D do // iterate over the domain in parallel
x[i] = reallyHeavyMatrixComputation();
D 的索引将在区域设置中循环分布,因此并行循环将在每个区域设置上创建任务,这些任务将执行区域设置的索引。因此,即使reallyHeavyMatrixComputation()
是完全本地计算,该循环也应该跨多个区域进行扩展。
在 Chapel 中编写可扩展并行循环的另一种方法是调用显式并行迭代器,该迭代器将跨语言环境本身分配工作。例如,Chapel 1.16 版添加了一个分布式迭代器包模块,该模块提供了为您分发工作的迭代器。回到第一个例子,如果它被重写为:
use DistributedIters; // make use of the distributed iterator module
var x: [1..N] real; // declare a local array
forall i in distributedDynamic(1..N) do // distribute iterations across locales
x[i] = reallyHeavyMatrixComputation(i);
那么迭代器的调用distributedDynamic
将成为循环的迭代,而不是范围1..N
和控制任务的创建。此迭代器使用指定的块大小(默认为 1)动态地将迭代处理到区域设置,因此可用于以可扩展的方式使用多个区域设置。有关更多详细信息,请参阅其文档