主要内容

改善parfor性能

你可以提高性能parfor以各种方式循环。这包括并行创建数组内循环;分析parfor循环;切片数组;和优化你的代码在本地工人在一个集群上运行。

在创建数组

当你在客户端创建一个大阵parfor循环,在循环访问它,你可以观察缓慢的代码的执行。为了提高性能,告诉每一个MATLAB®职工创建自己的数组,或部分的并行执行。您可以保存的时间从客户端传输数据到工人要求每个工人这些数组的创建自己的副本,同时,内部循环。考虑改变你的惯例之前初始化变量内循环,避免不必要的重复循环。你可能会发现,并行创建数组内的循环提高了性能。

性能改进取决于不同的因素,包括

  • 数组的大小

  • 时间需要创建数组

  • 工人获得全部或部分的数组

  • 每个工人的循环迭代数量执行

考虑所有因素当你正在考虑将此列表循环,parfor循环。更多细节,请参阅for循环转换成parfor-Loops

作为一种替代方法,考虑parallel.pool.Constant函数来建立变量在循环池的工人。这些变量在循环结束后工人,并保持对多个可用parfor循环。你可能会提高性能parallel.pool.Constant,因为数据是只有一次转移到工人。

在本例中,您首先创建一个大的数据集D和执行parfor循环访问D。然后使用D建立一个parallel.pool.Constant对象,它允许您重用数据通过复制D每个工人。测量时间使用抽搐toc针对每种情况,请注意区别。

函数constantDemo D =兰德(1 e7, 1);抽搐我= 1:20 = 0;parforj =一60 = a +和(D);结束结束toc抽搐D = parallel.pool.Constant (D);我= 1:20 b = 0;parforj =一60 b = b +总和(D.Value);结束结束toc结束
> > constantDemo开始平行池(parpool)使用过程的概要文件…连接到4工人。运行时间是63.839702秒。运行时间是10.194815秒。
在第二种情况下,你只有一次发送数据。你可以增强的性能parfor循环利用parallel.pool.Constant对象。

分析parfor循环

您可以配置文件parfor使用循环通过测量时间抽搐toc。您还可以测量多少数据转移的工人通过使用并行池ticBytestocBytes。注意,这是不同于在通常意义上使用MATLAB分析MATLAB代码分析器,明白了概要文件代码来提高性能

这个例子计算矩阵的谱半径和转换循环到一个parfor循环。测量得到的加速和传输数据。

  1. 在MATLAB编辑器中,输入以下循环。添加抽搐toc测量时间。将文件保存为MyForLoop.m

    函数一个= MyForLoop抽搐我= 1:200 (i) = max (abs (eig(兰德(a))));结束toc结束
  2. 运行代码,注意时间。

    一个= MyForLoop (500);
    运行时间是31.935373秒。

  3. MyForLoop.m,替换循环用parfor循环。添加ticBytestocBytes测量多少数据转移的工人在并行池。将文件保存为MyParforLoop.m

    ticBytes (gcp);parfor我= 1:200 (i) = max (abs (eig(兰德(a))));结束tocBytes (gcp)

  4. 运行新代码,并再次运行它。注意,第一个比第二个慢跑,因为平行池必须开始,你必须使可用的代码工人。请注意第二运行花费的时间。

    默认情况下,MATLAB自动打开一个平行的工人在本地机器上。

    一个= MyParforLoop (500);
    开始平行池(parpool)使用过程的概要文件…连接到4工人……BytesSentToWorkers BytesReceivedFromWorkers _____________ ________________________ 1 15340 7024 13328 5712 3 13328 5704 13328 5728 55324 24168运行时间是10.760068秒。
    运行时间是31.9秒在串行和并行10.8秒,并显示该代码转换成一个受益parfor循环。

切片数组

如果一个变量初始化之前parfor内循环,然后使用parfor循环,它必须被传递给每一个MATLAB工人评估循环迭代。只有那些变量在循环中使用从客户机传递工作区。然而,如果出现的所有变量由循环变量索引,每个工人只接收数组需要的一部分。

作为一个例子,首先运行一个parfor循环使用切片变量和测量时间。

%切片版本M = 100;N = 1 e6;data =兰德(M, N);抽搐parforidx = 1: M out2 (idx) =总和(数据(idx:)) / N;结束toc
运行时间是2.261504秒。

现在假设你不小心使用的引用变量数据而不是Nparfor循环。这里的问题是,调用大小(数据,2)将切片变量转换成一个广播(non-sliced)变量。

%不小心non-sliced版本明确M = 100;N = 1 e6;data =兰德(M, N);抽搐parforidx = 1: M out2 (idx) =总和(数据(idx,:))。/大小(数据,2);结束toc
运行时间是8.369071秒。
注意,意外的运行时间大于广播变量。

在这种情况下,您可以很容易地避免non-sliced使用数据,因为结果是一个常数,计算外循环。一般来说,您可以执行计算,只取决于广播数据循环开始之前,由于广播数据不能修改内部循环。在这种情况下,计算简单,结果在一个标量结果,所以你受益于计算的循环。

优化本地集群和工人

当地工人上运行您的代码可以提供方便的测试您的应用程序不需要使用集群的资源。然而,有一些缺点或局限性使用当地工人。因为传输数据不发生在网络上,转让行为当地工人可能不是表明它将如何通常发生在网络上。

与当地工人,因为所有的MATLAB工人会话正在运行在同一台机器上,你可能不会看到任何性能改进的parfor关于执行时间循环。这可能取决于许多因素,包括有多少核心处理器和机器。这里的关键是,集群可能会比你的本地机器上可用的核心。如果您的代码可以通过MATLAB多线程,然后更快的唯一方法是使用更多的核心问题的解决方案,使用一个集群。

你可能实验是否快来创建前的数组循环下面的左边(如图所示),而不是每个工人创造自己的数组循环内的右边(如图所示)。

试试下面的例子在本地运行并行池,注意时间的差异为每个循环执行。首先打开一个本地平行池:

parpool (“过程”)

运行下面的例子,并再次执行。注意,第一次运行针对每种情况比第二运行慢,因为平行池必须开始,你必须使可用的代码工人。注意时间,针对每种情况,第二运行。

抽搐;n = 200;M =魔法(n);R =兰德(n);parfori = 1: n (i) =总和(M(我:)。* R (n +我,:));结束toc
抽搐;n = 200;parfori = 1: n M =魔法(n);R =兰德(n);一笔(我)= (M(我:)。* R (n +我,:));结束toc

运行在一个远程集群,您可能会发现不同的行为,由于工人可以同时创建数组,节省传输时间。因此,代码优化为集群优化的本地工人可能不是工人,反之亦然。

另请参阅

相关的话题