Main Content

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

在多个数据集上运行单个程序

简介

单程序多数据 (spmd) 语言构造允许串行和并行编程的无缝交错。spmd 语句允许您定义一个代码块以在多个工作进程上同时运行。在工作进程的 spmd 语句内分配的变量允许通过 Composite 对象引用直接从客户端访问它们的值。

本章解释了 spmd 语句和 Composite 对象的一些特征。

何时使用 spmd

spmd 的“单程序”特点意味着相同的代码在多个工作进程上运行。您在 MATLAB® 客户端中运行一个程序,其中标记为 spmd 代码块的部分在工作进程上运行。当 spmd 代码块完成后,您的程序将继续在客户端运行。

“多数据”方面意味着即使 spmd 语句在所有工作进程上运行相同的代码,每个工作进程对于该代码可以拥有不同的、唯一的数据。因此,多个数据集可由多个工作进程容纳。

适合 spmd 的典型应用是那些需要在多个数据集上同时执行程序的应用,此时需要在工作进程之间进行通信或同步。一些常见情况如下:

  • 需要很长时间才能执行的程序 - spmd 允许多个工作进程同时计算解决方案。

  • 在大型数据集上运行的程序 - spmd 让数据分发给多个工作进程。

有关详细信息,请参阅 在 spmd、parfor 和 parfeval 之间选择

定义 spmd 语句

spmd 语句的一般形式为:

spmd
    <statements>
end

注意

如果并行池没有运行,spmd 将使用您的默认集群配置文件创建一个池(如果您的并行选项已相应设置)。

<statements> 表示的代码块在并行池中的所有工作进程上同时并行执行。如果您希望将执行限制在这些工作进程中的一部分,请准确指定要运行的工作进程数量:

spmd (n)
    <statements>
end

该语句要求 n 个工作进程运行 spmd 代码。n 必须小于或等于打开的并行池中的工作进程数量。如果池足够大,但是 n 工作进程不可用,则该语句将等待,直到有足够的工作进程可用。如果 n 为 0,则 spmd 语句不使用工作进程,并在客户端本地运行,就像当前没有正在运行的池一样。

您可以指定工作进程数量的范围:

spmd (m,n)
    <statements>
end

在这种情况下,spmd 语句至少需要 m 个工作进程,最多需要 n 个工作进程。

如果控制执行 spmd 语句的工作进程数量很重要,请在集群配置文件中或使用 spmd 语句设置精确的数字,而不是使用范围。

例如,针对三个工作进程创建一个随机矩阵:

spmd (3)
    R = rand(4,4);
end

注意

本章中所有后续示例均假设并行池处于打开状态,并且在 spmd 语句序列之间保持打开状态。

parfor 循环不同,用于 spmd 语句的每个工作进程对于 spmdIndex 都有一个唯一的值。这使您可以指定仅在某些工作进程上运行的代码,或者自定义执行,通常是为了访问唯一的数据。

例如,根据 spmdIndex 创建不同大小的数组:

spmd (3)
    if spmdIndex==1 
        R = rand(9,9);
      else
        R = rand(4,4);
    end
end

根据 spmdIndex 在每个工作进程上加载唯一的数据,并在每个工作进程上使用相同的函数从数据中计算结果:

spmd (3)
    labdata = load(['datafile_' num2str(spmdIndex) '.ascii'])
    result = MyFunction(labdata)
end

执行 spmd 语句的工作进程同时操作并且相互了解。与通信作业一样,您可以直接控制工作进程之间的通信,在它们之间传输数据,并在它们之间使用协同分布数组。

例如,在 spmd 语句中使用协同分布数组:

spmd (3)
    RR = rand(30, codistributor());
end

每个工作进程都有一个 30×10 的协同分布数组 RR 段。有关协同分布数组的更多信息,请参阅 使用协同分布数组

显示输出

在并行池上运行 spmd 语句时,来自工作进程的所有命令行输出都会显示在客户端命令窗口中。由于工作进程是没有显示的 MATLAB 会话,所以来自池的任何图形输出(例如,图形窗口)根本不会显示。

MATLAB 路径

所有执行 spmd 语句的工作进程必须具有与客户端相同的 MATLAB 搜索路径,以便他们可以执行在其公共代码块中调用的任何函数。因此,无论何时在客户端上使用 cdaddpathrmpath,如果可能的话,它也会在所有工作进程上执行。有关更多信息,请参阅 parpool 参考页。当工作进程在与客户端不同的平台上运行时,使用函数 pctRunOnAll 在所有工作进程上正确设置 MATLAB 路径。

错误处理

当工作进程在执行 spmd 语句期间发生错误时,该错误会报告给客户端。客户端尝试中断所有工作进程的执行,并向用户抛出错误。

工作进程上产生的错误和警告用工作进程 ID(spmdIndex)注释,并按照 MATLAB 客户端接收的顺序显示在客户端的命令窗口中。

如果在 spmd 的主体内使用,则 lastwarn 的行为在该代码块的末尾是未指定的。

spmd 限制

嵌套函数

在函数内部,spmd 语句的主体不能引用嵌套函数。但是,它可以通过将变量定义为嵌套函数的函数句柄来调用嵌套函数。

因为 spmd 函数体在工作进程上执行,所以由 spmd 语句内调用的嵌套函数更新的变量不会在外部函数的工作区中更新。

嵌套 spmd 语句

spmd 语句的主体不能直接包含另一个 spmd。但是,它可以调用包含另一个 spmd 语句的函数。内部的 spmd 语句不在另一个并行池中并行运行,而是在运行其包含函数的工作进程上的单个线程中串行运行。

嵌套 parfor 循环

spmd 语句不能包含 parfor 循环,并且 parfor 循环的主体不能包含 spmd 语句。原因是工作进程无法启动或访问进一步的并行池。

breakcontinuereturn 语句

spmd 语句的主体不能包含 breakcontinuereturn 语句。考虑使用 parfevalparfevalOnAll 而不是 spmd,因为您可以在它们上使用 cancel

全局变量和持久变量

spmd 语句的主体不能包含 globalpersistent 变量声明。原因是这些变量在工作进程之间不同步。您可以在函数中使用 globalpersistent 变量,但它们的值只有创建它们的工作进程才可见。与使用 global 变量相比,使用函数参量来共享值是一种更好的做法。

匿名函数

spmd 语句的主体不能定义匿名函数。但是,它可以通过函数句柄引用匿名函数。

inputname 函数

spmd 内部不支持使用 inputname 返回与参量编号对应的工作区变量名称。原因是 spmd 工作进程无法访问 MATLAB 桌面的工作区。为了解决此问题,请在 spmd 之前调用 inputname,如下例所示。

a = 'a';
myFunction(a)

function X = myFunction(a)
name = inputname(1);
spmd
    X.(name) = spmdIndex;
end
X = [X{:}];
end
    

load 函数

spmd 语句内不支持未分配给输出结构的 load 语法。在 spmd 内部,始终将 load 的输出分配给一个结构。

narginnargout 函数

spmd 语句中不支持以下用法:

  • 使用不带函数参量的 narginnargout

  • 使用 narginchknargoutchk 来验证当前正在执行的函数调用中的输入或输出参量的数量

原因是工作进程无法访问 MATLAB 桌面的工作区。为了解决此问题,请在 spmd 之前调用这些函数。

myFunction('a','b')

function myFunction(a,b)
nin = nargin;
spmd
    X = spmdIndex*nin;
end
end
    

P 代码脚本

您可以从 spmd 语句中调用 P 代码脚本文件,但 P 代码脚本不能包含 spmd 语句。要解决此问题,请使用 P 代码函数而不是 P 代码脚本。

ans 变量

spmd 语句内不支持对在 spmd 语句外定义的 ans 变量的引用。在 spmd 语句的主体内,必须先分配 ans 变量,然后才能使用它。

另请参阅

| | | | |

相关主题