Matlab 并行运算的尝试

1. 
https://ww2.mathworks.cn/matlabcentral/answers/46102-when-to-use-spmd-and-parfor-function

这是一个非常简短的摘要:
PARFOR比SPMD使用起来简单得多,通常在尝试并行化独立计算的集合时,它通常是您的首选。您需要确保您的计算不依赖于顺序(即,它们一定不能依赖于先前计算的结果)。
SPMD较难使用,但允许使用labSend和labReceive的工作人员之间进行通信。如果您希望为分布式阵列实现新功能,这也是合适的选择。


2.
https://ww2.mathworks.cn/matlabcentral/answers/48871-best-approach-to-this-problem-spmd-or-parfor
我想说这听起来像是您的PARFOR解决方案可能接近您可以做的最好的事情。听起来您的问题很适合PARFOR-很多独立的工作要做。使用SPMD可以实现相同的目的,但是您将无法获得PARFOR所提供的自动负载平衡功能,因此最终运行效率可能会降低。
您可能考虑的一件事是将PARFOR循环移动到外部循环,因为这将减少与并行运行相关的一些开销。


3.

https://stackoverflow.com/questions/12385534/spmd-vs-parfor

spmd是并行区域,而parfor是并行for循环。区别在于,在spmd区域中,您可以并行执行的任务具有更大的灵活性。您可以编写一个for循环,可以对分布式数组和向量进行操作。您可以对整个工作流程进行编程,该工作流程通常包含多个循环。这是有代价的:您需要更多地了解如何在线程之间分配工作和数据。例如,并行化循环需要在工作线程之间显式地划分循环索引范围(通过使用labindex在代码中进行此操作),并可能创建分布式数组。
另一方面,parfor仅这样做-并行化的for循环。您可以添加自动并行化的工作,因此工作可以通过MATLAB在工作人员之间进行划分。
如果只想并行运行一个循环,然后再在本地客户端上处理结果,则应使用parfor。如果要并行化整个MATLAB程序,则必须处理spmd和工作分配的复杂性。

4.

spmd如果您在计算期间需要worker之间的通信,请使用此选项。
parfeval在以下情况下使用:
  ● 您想在后台运行计算。
  ● 每个任务都依赖于其他任务。

5.
https://ww2.mathworks.cn/help/parallel-computing/choose-spmd-parfor-parfeval.html

通信并行代码
要运行在并行计算,可以使用parfor, parfeval,parfevalOnAll,或 spmd。每个构造都依赖于不同的并行编程概念。如果你要求工人在整个计算,用于通信 parfeval,parfevalOnAll或 spmd。
  ● 如果您的代码可以分为一组任务,请使用parfeval或parfevalOnAll,其中每个任务可以取决于其他任务的输出。
  ● spmd如果您在计算期间需要工作人员之间的通信,请使用此选项。
与parfeval的计算最好用图形表示,类似于带阻塞的看板。通常,计算完成后会从工作人员那里收集结果。您可以parfeval使用afterEach 或从执行操作中收集结果 afterAll。通常将结果用于进一步的计算。
spmd类似于瀑布式工作流程,用最好用流程图表示。执行spmd 语句的池工作程序称为实验室。可以在计算过程中从实验室收集结果。有时,实验室必须与其他实验室进行通信才能完成计算。
如果不确定,请问自己以下问题:在我正在交流的并行代码中,无需工人之间的任何交流就可以完成每个计算吗?如果是,请使用 parfeval。否则,请使用spmd。
同步和异步工作
当之间进行选择parfor, parfeval和spmd,考虑你的计算是否需要与客户端同步。
parfor并spmd要求同步,因此从MATLAB上运行的任何新的计算结果阻止你®客户端。parfeval不需要同步,因此客户端可以自由地从事其他工作。
比较多线程性能和 ProcessPool
查看MATLAB命令
在此示例中,您将比较快速功能在客户端和上运行的速度ProcessPool。一些MATLAB函数使用多线程。使用这些功能的任务在多个线程上的性能要优于单个线程。因此,如果在具有多个内核的计算机上使用这些功能,则本地群集的性能可能比客户端上的多线程性能差。
如果在客户端上执行多个执行的速度比-loop更快clientFasterThanPool,则返回本示例末尾列出的支持功能。语法与以下内容相同:将函数句柄用作第一个参数,将输出数量用作第二个参数,然后为该函数提供所有必需的参数。trueparforparfeval
首先,创建一个local ProcessPool。
p = parpool('local');
使用``本地''配置文件启动并行池(parpool)...
连接到并行池(工人人数:6)。

eig使用clientFasterThanPool支持功能检查功能运行的速度。创建一个匿名函数eig以代表您的函数调用。
[〜,t_client,t_pool] = clientFasterThanPool(@(N)eig(randn(N)),0,500)
t_client = 22.6243

t_pool = 4.9334

并行池比客户端更快地计算答案。除以t_client通过maxNumCompThreads查找客户端上的每个线程所花费的时间。
t_client / maxNumCompThreads
年= 3.7707

默认情况下,工作进程是单线程的。结果表明,客户端和池上每个线程花费的时间相似,因为的值t_pool大约是的1.5倍t_client/maxNumCompThreads。该eig功能无法从多线程中受益。
接下来,lu使用clientFasterThanPool支持功能检查该功能运行的速度。
[〜,t_client,t_pool] = clientFasterThanPool(@(N)lu(randn(N)),0,500)
t_客户端= 1.0225

t_pool = 0.4693

如果本地计算机具有四个或更多核心,那么并行池通常比客户端更快地计算答案。除以t_client通过maxNumCompThreads找到每个线程所花费的时间。
t_client / maxNumCompThreads
年= 0.1704

此结果表明,客户端上每个线程花费的时间比池中少得多,因为的值t_pool大约是的3倍t_client/maxNumCompThreads。每个线程使用较少的计算时间,表明lu使用多线程。
定义辅助函数
支持功能clientFasterThanPool检查客户端上的计算是否比并行池上的计算更快。它以函数句柄fcn和可变数量的输入参数(in1, in2, ...)作为输入。clientFasterThanPool执行fcn(in1, in2, ...)客户端和活动并行池两者上。例如,如果要测试rand(500),则函数句柄必须采用以下形式:
fcn = @(N)rand(N);
然后,使用clientFasterThanPool(fcn,500)。
函数[结果,t_multi,t_single] = clientFasterThanPool(fcn,numout,varargin)
     %为输出预分配单元格数组
    输出= cell(numout);
    
    客户百分比
    抽动
    对于i = 1:200
        如果numout == 0
            fcn(varargin {:});
        其他
            [outputs {1:numout}] = fcn(varargin {:});
        年底
    结束
    t_multi = toc;
    
    %平行泳池
    vararginC = parallel.pool.Constant(varargin);
    抽动
    parfor i = 1:200
         %为输出预分配单元格数组
        输出= cell(numout);
        
        如果numout == 0
            fcn(vararginC.Value {:});
        其他
            [outputs {1:numout}] = fcn(vararginC.Value {:});
        年底
    结束
    t_single = toc;
    
    %如果多线程化更快,则返回true
    结果= t_single> t_multi;
结束
比较性能parfor,parfeval和spmd
查看MATLAB命令
取决于计算类型,使用spmd可能比使用parfor-loops或慢或快parfeval。开销会影响parfor-loopparfeval和的相对性能spmd。
对于一组任务,parfor并且parfeval通常执行优于spmd在这些条件下。
  ● 每个任务花费的计算时间不确定。
  ● 每个任务花费的计算时间不一致。
  ● 从每个任务返回的数据很小。
parfeval在以下情况下使用:
  ● 您想在后台运行计算。
  ● 每个任务都依赖于其他任务。
在此示例中,您检查了使用parfor-loop parfeval,和时执行矩阵运算的速度spmd。
首先,创建一个本地并行池p。
p = parpool('local');
使用``本地''配置文件启动并行池(parpool)...
连接到并行池(工人人数:6)。

计算随机矩阵
通过使用parfor-loop parfeval,和来检查生成随机矩阵的速度spmd。设置试验次数(n)和矩阵大小(对于m-bym矩阵)。增加试验次数可以改善以后分析中使用的统计信息,但不会影响计算本身。
m = 

1000;
n = 

20;
然后,使用parfor-looprand(m)对每个工作程序执行一次。为每个m试验安排时间。
parforTime = zeros(n,1);
因为我= 1:n
    抽动
    垫= cell(1,p.NumWorkers);
    PARFOR N = 1:p.NumWorkers
      mats {N} = rand(m);
    结束
    parforTime(i)= toc;
结束
接下来,用于为每个工作程序parfeval执行rand(m)一次。为每个m试验计时。
parfevalTime =零(n,1);
因为我= 1:n
    抽动
    f(1:p.NumWorkers)= parallel.FevalFuture;
    对于N = 1:p.NumWorkers
      f(N)= parfeval(@ rand,1,m);
    端
    垫= fetchOutputs(f,“ UniformOutput”,false)';
    parfevalTime(i)= toc;
    明确˚F
结束
最后,用于为每个实验spmd执行rand(m)一次。有关实验室及其执行命令的详细信息spmd,请参阅在多个数据集上运行单个程序。为每个m试验计时。
spmdTime = zeros(n,1);
因为我= 1:n
    抽动
    spmd
        e =兰特(m);
    结束
    eigenvals = {e {:}};
    spmdTime(i)= toc;
结束
用于rmoutliers从每个试验中删除异常值。然后,用于boxplot比较时间。
%隐藏异常值
boxData = rmoutliers([parforTime parfevalTime spmdTime]);

%剧情数据
箱线图(boxData,'标签',{ 'PARFOR' ,'parfeval' ,'SPMD' },'符号','' )
ylabel('时间(秒)')
title('制作n个随机矩阵(m×m)')

通常,spmd每次评估比parfor或需要更多的开销parfeval。因此,在这种情况下,使用parfor-loop或parfeval更有效。
计算随机矩阵之和
接下来,计算随机矩阵的总和。您可以通过减少变量和做到这一点parfor-loop,一笔带计算后parfeval,或gplus用spmd。再次,设置试验次数(n)和矩阵大小(对于m-副m矩阵)。
m = 

1000;
n = 

20;
然后,使用parfor-looprand(m)对每个工作程序执行一次。用归约变量计算总和。为每个m试验计时。
parforTime = zeros(n,1);
因为我= 1:n
    抽动
    结果= 0;
    PARFOR N = 1:p.NumWorkers
      结果=结果+ rand(m);
    结束
    parforTime(i)= toc;
结束
接下来,用于为每个工作程序parfeval执行rand(m)一次。使用fetchOutputs上的所有矩阵,然后使用sum。为每个m试验计时。
parfevalTime =零(n,1);
因为我= 1:n
    抽动
    f(1:p.NumWorkers)= parallel.FevalFuture;
    对于N = 1:p.NumWorkers
      f(N)= parfeval(@ rand,1,m);
    结束
    结果= sum(fetchOutputs(f));
    parfevalTime(i)= toc;
    明确˚F
结束
最后,用于为每个实验spmd执行rand(m)一次。用于gplus对所有矩阵求和。要将结果仅发送到第一个实验室,请将可选targetlab参数设置为1。为每个m试验计时。
spmdTime = zeros(n,1);
因为我= 1:n
    抽动
    spmd
        r = gplus(rand(m),1);
    结束
    结果= r {1};
    spmdTime(i)= toc;
结束
用于rmoutliers从每个试验中删除异常值。然后,用于boxplot比较时间。
%隐藏异常值
boxData = rmoutliers([parforTime parfevalTime spmdTime]);

%剧情数据
箱线图(boxData,'标签',{ 'PARFOR' ,'parfeval' ,'SPMD' },'符号','' )
ylabel('时间(秒)')
title('n个随机矩阵之和(m×m)')

对于此计算,spmd其速度明显快于parfor-loop或parfeval。在parfor-loop中使用归约变量时,会将-loop每次迭代的结果广播parfor给所有工作程序。相比之下,仅spmd调用gplus一次即可执行全局归约操作,所需的开销更少。这样,计算的减少部分的开销为O (ñ2)对于spmd和Ô (米ñ2)为parfor。
 

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页