简约操作

一、基本概念和并行原理

我们知道,只有当循环体内的操作相互独立时才可以用parfor关键字进行并行。但是有一类特殊的循环操作不受这个条件限制,这类操作我们称为简约操作。

注意:简约操作所对应的循环体并不独立,但是执行结果与执行顺序无关。

示例(求1到1000之和)

  a=0;   N=1000;	%给a和N赋值
  for i=1:N		%for循环变量i从1到N开始递增
       a=a+i;	%循环体执行的是a=a+i,a+i每次都替换a
  end	%循环结束

(a=a +i这是循环体,里面涉及到循环变量a+i ,等号后边的a 每次都是变换的,与循环变量有关并不是相互独立的,但是我们知道这1000个数相加,先加哪个和后加哪个是不影响结果的,所以这类操作仍然用并行循环来完成,而这个约定与之前的约定矛盾了,所以这类操作都归为简约操作。)

在执行for循环时,循环操作依赖于上次执行结果,但是最终结果和执行顺序无关。

Matlab对简约操作进行了处理,允许采用parfor关键字对简约操作对应的循环进行并行。最终结果与for循环结果一致。

将这个示例可以推广,只要是求和问题满足(其中f(i)是关于i的表达式)。

Matlab中简约操作的并行原理:

(把执行任务由客户端发给各个work,各个work执行相同的程序副本,变量i是不一样的,执行完之后,各个work在把执行结果发给客户端,客户端再进行汇总,得出结果)

二、简约操作并行效率分析

对于不同的函数f,对应的计算量不同,从而影响简约操作的并行效率。我们只分析一种简单情形:

示例

function [tparfor,tfor]=partry16(nn)
a=0;
mypool=parpool;    %打开并行计算池
tic;    %计时开始
parfor kk=1:nn    %并行循环开始执行
       a=a+kk;    %a加循环变量kk赋给等号前面的a,关于数的累加运算
end    %结束并行循环
tparfor=toc;    %计时结束,把并行循环的运行时间赋给tparfor
delete(mypool)    %关闭并行计算池
display(strcat('partry16',':','parfor:',num2str(tparfor),'seconds'));
%显示并行循环执行的时间
b=0;
tic;    %计时开始
for kk=1:nn    %串行循环开始
    a=a+kk;    %累加运算
end    %结束串行循环
tfor=toc;    %计时结束,把串行循环的运行时间赋给tfor
display(strcat('partry16',':','for:',num2str(tfor),'seconds'));
%显示串行循环的执行时间

可以发现,随着循环次数的增加,parfor关键字的并行效率开始提高。

三、简约操作的执行过程

初始计算时,初值不会从client传输到worker;  

遇到关键字parfor,循环被分段分配到worker;  

各worker分段独立执行循环体内的操作;  

各个worker计算完后结果传输至client;  

client将各个结果进行综合得到最终结果。

四、简约操作与简约变量的特征

在Matlab程序设计中,称满足简约操作的操作符为简约操作符。简约操作符的操作对象称为简约变量(只有在parfor中才有意义)。

简约操作是一种特殊的操作,其操作结果与操作顺序无关。下面我们给出一些简约操的表达形式: x=x+expr; x=x-expr; x=x.*expr; x=x*expr x=x&expr; x=x|expr;x=[x,expr];   x=[x;expr];  x={x,expr};    x={x;expr}; x=min(x,expr);    x=max{x,expr}; x=union(x,expr);    x=intersect(x,expr)。以上操作和变量可以调换位置。

简约变量在parfor中应该满足一些要求

1、简约变量只能出现在简约赋值操作的表达式中  

简约操作可以由上面给的各种操作符引导,也可以自己定义。

简约操作的表达式:x=f(x,expr) 其中x为简约变量,expr为表达式,f为符合简约操作的函数。

注意:如果f为变量,需要在parfor之前赋值,不能在parfor中赋值。

在Matlab操作符中,&&和||操作符不能进行简约操作。

%错误用法
f = @(x,k)x  * k;	%@定义一种运算,x与k相乘。(循环体外)
parfor i = 1:n
	a = f(a,i)	  %执行运算
	f = @times;  %又用@定义了一种运算。这里是错误点,@这种运算是不能在并行循环中去定义,它只能在并行循环外去定义。
end
%正确用法
f = @(x,k)x * k ;
partfor i = 1 : n
	a = f(a,i)
end

2、在同一parfor中,对简约变量的操作必须一致。

 %错误用法
parfor i = 1:n
if A>5*k
A = A +i; 		%执行A+i的替换
else
A = [A,4+i];	%执行A的增长,与前面A = A +i;操作不一致
end		%if语句结束
end
%正确用法
parfor i = 1:n
if  A>5*k
A = A +i;
else
A = a +i+5*k;
end		%if语句结束
end

3、如果简约变量的操作是‘*’或者‘[]’,x在操作符前面或者后面都可以,但是位置必须恒定。

%错误用法
parfor i = 1:n
if A > 5*k
A = [A ,4+i];
else
A =[r(i),A];	%这是错误点
end
%正确用法
parfor i = 1:n
if A > 5*k
A = [A ,4+i];
else
A =[A,r(i)];
end

4、简约变量赋值应满足结合律和交换律

结合律:f(a,f(b,c))=f(f(a,b),c)

交换律:f(a, b)=f(b,a)

在Matlab中,*、[ ]、{ }均不满足交换律,但是Matlab对于这些运算符做了特殊处理,可以保证这些操作执行结果的正确性。

五、程序示例

结合律

加法

function  [ ]=partry21(N)
data=peaks;     %peaks函数生成一些数据
data=data(:);
if N>length(data(:))
   N=length(data(:));
end    %容错,若输入参数过大,则赋给N
out=0;    %输出,初始值为0
for kk=1:N-1
    out=myadd(out,data(kk));    %利用串行循环对数据做加法运算
end
display(strcat('for,myadd,最终结果:',num2str(out)));    %显示输出结果
out=0; 
mypool=parpool;
parfor kk=1:N-1
       out=myadd(out,data(kk));
end
delete(mypool)
display(strcat('parfor,myadd,最终结果:',num2str(out)));

myadd.m

function [out]=myadd(a,b)
        out = a+b;

可以看出加法符合结合律

减法

function  [ ]=partry21(N)
data=peaks; 
data=data(:);
if N>length(data(:))
   N=length(data(:));
end
out=0;
for kk=1:N-1
   out=mysub(out,data(kk));
end
display(strcat('for,mysub,最终结果:',num2str(out)));
out=0;
mypool=parpool;
parfor kk=1:N-1
      out=mysub(out,data(kk));
end
delete(mypool)
display(strcat('parfor,mysub,最终结果:',num2str(out)));

mysub.m

function [out]=mysub(a,b)
        out = a-b;

可以看出减法不符合结合律。

交换律

function [ ]=partry22(N)
data=[rand(N,1) (1:N).'];   %生成一个随机向量,第二列的列向量为1到N
maxv=[-1 0];    %取一个初始向量
mypool=parpool;
parfor ii=1:N
    maxv=mymax(maxv,data(ii,:));     %两个向量相比较,取最大
end
disp(maxv);
delete(mypool)
maxv=[-1 0];
for ii=1:N
    maxv=mymax(maxv,data(ii,:));
end
disp(maxv);

mymax.m

function [ out ] = mymax(in1,in2)
if in1(1)>in2(1)
    out = in1;
else
    out = in2;
end

可以看出满足交换律。

发布了155 篇原创文章 · 获赞 124 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_44762986/article/details/104879810