[已解决] 并行计算的错误

[复制链接]
郑之恒 发表于 2021-3-31 14:07:10
A是一个矩阵;
B=[];
for i=1:10
    tmp=func(A);
   eval(['A' num2str(i) '= tmp'])
    B=[B;"A"+num2str(i) ];
end
C=B;
使用parfor会错误,把eval放进函数,
B=[];
parfor i=1:10
    tmp=func(A);
    B=func2(B);
end
C=B;
会显示B未初始化,把B=[]放进循环,会显示未定义B;
但是B与上一次循环的值是有关联的,应该不能放进循环,改如何改?

最佳答案


gywxd 发表于 2021-4-6 19:47:15
本帖最后由 gywxd 于 2021-4-6 19:49 编辑

一个程序并行时要共享内存,而eval语句可能使程序进入错误的workspace,因此不要用eval

你好好看看par  的参数隔离说明
简单来说par 并行 就是在程序开始运行之前,把需要处理的 和 i 相关的多个变量 分片 分配到多个workspace 里面在各个space里面分别同时运行,并将结构存入相应的 结构里面,运行完成后又把这些结果安装分配是的顺序组合。

这就要求每次 for 循环里面的运算是独立的不关联和彼此依赖的,否则如何并行,这个for循环,等等另外一个 循环的结果才能运算。
parfor  i=1:10
A(i)= A(i)+c;
end      这样的没问题

parfor  i=1:10
A(i)= A(i)+A(i-1);
end
这样的不行, 运算不独立

通常消耗最多计算资源的程序往往是循环。把循环并行化,或者优化循环体中的代码是最常用的加快程序运行速度的思路。
Matlab提供了parfor关键字,可以很方便的在多核机器或集群上实现并行计算。

parfor关键字的使用
由for关键字引导的循环通常为串行运行,如果改为parfor则可以由多个worker以并行方式执行。
parfor可以将n次循环分解为独立不相关的m部分,然后将各部分分别交给一个worker执行。
循环执行的结果应该与n次循环执行的顺序无关。

parfor中的变量类型
简约变量
一般parfor中各次循环对应的运算应该相互独立,但简约操作可以在多次循环内同时对一个变量操作。这种变量称为简约变量。例如下方代码中a就是简约变量。
a = 0;
for i = 1:1000
a = a+i;
end
简约操作包括+ - * .* & | [,] [;] {,} {;} min max union intersect。
同一个parfor循环对简约变量的操作必须一致,即必须是同一种简约操作符。而且与操作符的相对位置也必须一致。
简约变量赋值表达式应该满足结合律和交换律。* [] {}底层有特殊处理保证结果的正确性。

切片变量(sliced)
parfor中可能需要读取或写入parfor之外的矩阵,读取写入位置与循环变量相关。这样就需要向worker传输大量的数据。
矩阵如果被Matlab识别为切片变量,则数据可以分段传输到各worker,提高传输效率。
切片变量矩阵的大小是不可在parfor中改变的,且为了保证Matlab识别正确,每次循环中只能读取由同一个索引值索引的切片,如a a[i+1]同时出现则a不被识别为切片变量。

循环变量(loop)
如上例中的i,表示当前循环的id。

广播变量(broadcast)
在parfor之前赋值,在parfor内只进行读取操作,不能再parfor之内对其赋值。若在parfor以内对广播变量赋值,则会显示“the variable xxxx in a parfor cannot be classified.”

临时变量(temporary)
作用域局限于parfor内,parfor结束后不存在。不影响parfor之前声明的同名变量。

各种变量区分的例子
下例中,parfor中的tmp是临时变量,parfor结束后tmp的值依然是5,不受临时变量的影响。
broadcast是广播变量,每次循环中的值不变。
redued是简约变量,Matlab对其的值将分段由各worker计算后送回主进程处理。
sliced为切片变量,数据传输有优化提升。
i为循环变量。

    tmp = 5;     broadcast = 1;   
reduced = 0;   
sliced = ones(1, 10);   
parfor i = 1:10      
         tmp = i;
         reduced = reduced + i + broadcast;      
         sliced(i) = sliced(i) * i;   
end

回复此楼

1 条回复


gywxd 发表于 2021-4-6 19:47:15
本帖最后由 gywxd 于 2021-4-6 19:49 编辑

一个程序并行时要共享内存,而eval语句可能使程序进入错误的workspace,因此不要用eval

你好好看看par  的参数隔离说明
简单来说par 并行 就是在程序开始运行之前,把需要处理的 和 i 相关的多个变量 分片 分配到多个workspace 里面在各个space里面分别同时运行,并将结构存入相应的 结构里面,运行完成后又把这些结果安装分配是的顺序组合。

这就要求每次 for 循环里面的运算是独立的不关联和彼此依赖的,否则如何并行,这个for循环,等等另外一个 循环的结果才能运算。
parfor  i=1:10
A(i)= A(i)+c;
end      这样的没问题

parfor  i=1:10
A(i)= A(i)+A(i-1);
end
这样的不行, 运算不独立

通常消耗最多计算资源的程序往往是循环。把循环并行化,或者优化循环体中的代码是最常用的加快程序运行速度的思路。
Matlab提供了parfor关键字,可以很方便的在多核机器或集群上实现并行计算。

parfor关键字的使用
由for关键字引导的循环通常为串行运行,如果改为parfor则可以由多个worker以并行方式执行。
parfor可以将n次循环分解为独立不相关的m部分,然后将各部分分别交给一个worker执行。
循环执行的结果应该与n次循环执行的顺序无关。

parfor中的变量类型
简约变量
一般parfor中各次循环对应的运算应该相互独立,但简约操作可以在多次循环内同时对一个变量操作。这种变量称为简约变量。例如下方代码中a就是简约变量。
a = 0;
for i = 1:1000
a = a+i;
end
简约操作包括+ - * .* & | [,] [;] {,} {;} min max union intersect。
同一个parfor循环对简约变量的操作必须一致,即必须是同一种简约操作符。而且与操作符的相对位置也必须一致。
简约变量赋值表达式应该满足结合律和交换律。* [] {}底层有特殊处理保证结果的正确性。

切片变量(sliced)
parfor中可能需要读取或写入parfor之外的矩阵,读取写入位置与循环变量相关。这样就需要向worker传输大量的数据。
矩阵如果被Matlab识别为切片变量,则数据可以分段传输到各worker,提高传输效率。
切片变量矩阵的大小是不可在parfor中改变的,且为了保证Matlab识别正确,每次循环中只能读取由同一个索引值索引的切片,如a a[i+1]同时出现则a不被识别为切片变量。

循环变量(loop)
如上例中的i,表示当前循环的id。

广播变量(broadcast)
在parfor之前赋值,在parfor内只进行读取操作,不能再parfor之内对其赋值。若在parfor以内对广播变量赋值,则会显示“the variable xxxx in a parfor cannot be classified.”

临时变量(temporary)
作用域局限于parfor内,parfor结束后不存在。不影响parfor之前声明的同名变量。

各种变量区分的例子
下例中,parfor中的tmp是临时变量,parfor结束后tmp的值依然是5,不受临时变量的影响。
broadcast是广播变量,每次循环中的值不变。
redued是简约变量,Matlab对其的值将分段由各worker计算后送回主进程处理。
sliced为切片变量,数据传输有优化提升。
i为循环变量。

    tmp = 5;     broadcast = 1;   
reduced = 0;   
sliced = ones(1, 10);   
parfor i = 1:10      
         tmp = i;
         reduced = reduced + i + broadcast;      
         sliced(i) = sliced(i) * i;   
end

回复此楼
您需要登录后才可以回帖 登录 | 注册

本版积分规则

相关帖子
热门教程
站长推荐
快速回复 返回顶部 返回列表