使用parfor循环:开始运行
请注意
.
注意:matlabpool在2015年被移除,你应该用parpool代替。
今天我要介绍一位客座博主,莎拉等Zaranek他是The MathWorks的一名应用工程师。莎拉此前曾写关于加速来自客户的代码以获得可接受的性能。她将再次写关于加速MATLAB应用程序,但这一次她的重点将是使用并行计算工具。
内容
简介
我想写一篇文章来帮助用户更好地理解我们的并行计算工具。在这篇文章中,我将关注这些工具中比较常用的一个函数:parfor循环。
这篇文章将专注于获得一个并行代码使用parfor启动并运行。本文不讨论性能问题。我将假设读者有一个基本的知识parfor循环结构。罗兰有一个很好的关于使用的介绍parfor在她之前的一个的帖子.还有一些不错的介绍视频。
为了清晰起见,请注意:自从Loren的介绍性帖子以来,用于并行计算的工具箱的名称已经从分布式计算工具箱更改为并行计算工具箱.这不是两个独立的工具箱。
方法
在某些情况下,您可能只需要更改一个为循环,parfor-loop使它们的代码并行运行。但是,在其他情况下,您可能需要稍微更改代码,以便parfor可以工作。我决定展示一些例子,强调人们可能会遇到的主要挑战。我将这些例子分为四类:
- 独立
- 全局变量和透明度
- 分类
- 独特性
背景parfor-loops
在一个parfor-loop(就像在标准为-loop)一系列被称为循环体的语句在一个值范围内迭代。然而,当使用parfor迭代不是在客户端MATLAB机器上运行,而是在MATLAB工作者上并行运行。
每个员工都有自己独特的工作空间。因此,进行这些计算所需的数据从客户端发送给工人,结果被发送回客户端并拼接在一起。最酷的是parfor是否为用户处理数据传输。当MATLAB到达parfor-循环,它静态分析的主体parfor-循环,并确定哪些信息将流向哪个工作者,哪些变量将返回到客户端MATLAB。在理解为什么对的使用施加特定约束时,理解这个概念将变得非常重要parfor.
打开matlabpool
在查看一些示例之前,我将打开一个matlabpool,以便并行运行循环。我将使用我的默认本地配置打开matlabpool(即,我的工作人员将在安装了MATLAB的双核笔记本电脑上运行)。
如果matlabpool (“大小”) = = 0正在检查我的池是否已经打开。matlabpool开放2结束
使用'local'配置启动matlabpool…连接2个实验室。
请注意:“大小”选项是R2008b中新增的。
独立
的parfor-loop是为任务并行类型的问题而设计的,其中循环的每次迭代都是独立于其他迭代的。这是使用parfor循环。让我们看一个每次迭代都不是独立的例子。
类型dependentLoop.m
依赖for循环的例子a = 0 (1,10);parfor it = 1:10 a(it) = someFunction(a(it));结束
使用M-Lint (MATLAB的静态代码分析器)检查上面的代码会给出一个警告消息,这些迭代是依赖的,将不能与parfor构造。M-Lint可以通过编辑器或命令行访问。在本例中,我使用命令行并定义了一个简单的函数displayMlint所以显示器是紧凑的。
输出= mlint (“dependentLoop.m”);displayMlint(输出)
由于变量'a'的使用方式,PARFOR循环无法运行。在PARFOR循环中,变量“a”以不同的方式被索引,这可能导致迭代之间的依赖关系。
有时循环本质上或不可避免地依赖,因此parfor不适合这种类型的计算。然而,在某些情况下,可以重新构造循环主体以消除依赖关系或将其从耗时的主要计算中分离出来。
全局变量和透明度
函数体中的所有变量parfor-loop必须是透明的。这意味着所有对变量的引用都必须出现在程序的文本中。由于MATLAB是静态分析循环来找出什么数据去了什么工作者,什么数据返回,这似乎是一个可以理解的限制。
因此,以下命令不能在类的主体中使用parfor循环:evalc,eval,evalin,assignin.负载也可以不使用除非输出的负载是分配到一个变量名。可以在调用的函数中使用上述函数parfor,因为函数有自己的工作空间。我发现这通常是解决透明度问题最简单的方法。
类的主体内不能定义全局变量或持久变量parfor循环。我还建议谨慎使用全局值,因为员工的全局值的变化不会自动反映在本地的全局值中。
分类
详细的描述分类变量的parfor-loop在文档中。我认为,将分类看作是表示变量在客户机和工作者之间传递的不同方式,以及它在对象体中使用的不同方式是有用的parfor循环。
挑战与分类
挑战往往出现在第一次转换时为循环,parfor-循环,因为这个分类有问题。一个常见的问题是嵌套的转换为-循环,其中切片变量没有适当的索引。
切片变量是每个工人计算变量的不同部分的变量。因此,切片变量在工作者中被切片或分割。切片变量用于防止不需要的数据从客户端传输到工作者。
使用parfor用嵌套为循环
下面的循环是嵌套的,并遇到了其中的一些限制parfor对切变量。
类型parforNestTry.m
A1 = 0 (10,10);A1(ix, jx) = ix + jx;结束结束
输出= mlint (“parforNestTry.m”);displayMlint(输出);
由于变量“A1”的使用方式,PARFOR循环无法运行。'A1'的有效索引在PARFOR循环中受到限制。
在这种情况下,A1是切片变量。对于切片变量,限制放在第一级变量索引上。这允许parfor轻松地将变量的正确部分分配给正确的工作人员。
一般来说,第一级索引是指在第一组圆括号或大括号内的索引。这是解释详细信息请参见文档中的分类部分。
这些一级指标之一必须是循环计数器变量或计数器变量加或减一个常数。其他一级索引必须是常量、非循环计数器变量、冒号或结束.
在这种情况下,A1有一个循环计数器变量,用于第一级索引(9而且jx).
的解决方案是确保循环计数器变量只是的指标之一A1将另一个索引设为冒号。要实现这一点,可以将内部循环的结果保存到一个新变量中,然后将该变量保存到嵌套循环外部所需的变量中。
A2 = 0 (10,10);parforix = 1:10 myTemp = 0 (1,10);为myTemp(jx) = ix + jx;结束: A2 (ix) = myTemp;结束
您还可以通过使用单元格来解决这个问题。自jx现在在第二级索引中,它可以是一个循环计数器变量。
A3 =细胞(10,1);parfor第九= 1:10为jx = 1:10 A3{ix}(jx) = ix + jx;结束结束A3 = cell2mat (A3);
我发现这两种解决方案各有好处。万博 尤文图斯虽然单元格可能更容易在代码中实现,但它们也会导致A3使用更多的内存由于附加内存细胞的要求。调用cell2mat还增加了额外的处理时间。
类似的技术可以用于嵌套的多个级别为循环。
独特性
进行特定机器的计算
这是一种方式,同时使用parfor-循环,以确定您在哪台机器上,并在循环中执行特定于机器的指令。为什么要这样做的一个例子是,如果不同的机器在不同的目录中有数据文件,而您想确保进入正确的目录。如果您将代码设置为特定于机器的,那么一定要小心,因为它将更难移植。
正在获取机器主机名[~,主机名]=系统(的主机名);如果循环迭代与matlabpool的大小相同,则%命令每个worker运行一次。parfor第九= 1:matlabpool (“大小”) [~,hostname {ix}] = system(的主机名);结束%然后可以执行主机/计算机特定的命令主机名=独特(hostnameID);checkhost =主机名(1);parfor第九= 1:matlabpool (“大小”[~,myhost] = system(的主机名);如果比较字符串(并且,checkhost)显示(“在机器1”)其他的显示器(“不在机器1号上”)结束结束
在机器1上在机器1上
在我的例子中,因为我是本地运行的——所有的工作人员都在同一台机器上。
下面是在非本地集群上运行的相同代码。
matlabpool关闭matlabpool开放快速parfor第九= 1:matlabpool (“大小”) [~,hostname {ix}] = system(的主机名);结束%然后可以执行主机/计算机特定的命令主机名=独特(hostnameID);checkhost =主机名(1);parfor第九= 1:matlabpool (“大小”[~,myhost] = system(的主机名);如果比较字符串(并且,checkhost)显示(“在机器1”)其他的显示器(“不在机器1号上”)结束结束
向所有实验室发出停止信号…停止了。使用“speedy”配置启动matlabpool…与16个实验室相连。在机器1上在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上不在机器1上
请注意:~这个特性是R2009b的新特性,在Loren之前的博客中讨论过的帖子.
进行特定员工的计算
我建议使用新的spmd进行特定工作者计算的功能。有关spmd,查看文档。
清理
matlabpool关闭
向所有实验室发出停止信号…停止了。
你的例子
告诉我一些你用过的方法parfor-循环或随时提出关于这里没有解决的与性能无关的问题。发表你的问题和想法在这里.