Arranged By Zhonglihao @ 2018
**请确认Matlab安装时点选了并行计算工具箱
变量问题
观察下面三个parfor索引语法:
parfor i = 0:0.2:1
parfor j = 1:2:11
parfor k = 12:-1:1
三句语法在parfor使用中均错误,第一句不能用小数作为递增值,第二句递增不为1,第三句递增值为负数,均不能使用,在parfor索引中,按照官方的意思就是只能使用 i = 1:1:n这样的递增是最保险的方法。
若确切需要使用小数递增方便理解的话,在parfor中应转为整数正向递增,如下代码所示例:
iValues = 0:0.2:1;
parfor idx = 1:numel(iValues)
i = iValues(idx);
…
end
观察以下代码片,左侧希望并行赋值x数组的和,然而x数组在循环外已被定义,在循环内重写x(1) x(2)的值,因为在parfor的范围内,因此x数组会被并行赋值,造成写竞争,所以左边的代码片是非法的,而右侧的x变量是循环里面临时生成的,因此具备并行计算的条件。
无效 | 有效 |
parfor idx = 1:10 x(1) = 7; x(2) = 8; out(idx) = sum(x); end | parfor idx = 1:10 x = [7, 8]; out(idx) = sum(x); end |
同理地,一下代码也出现了无法区分全局变量的问题,a采用了结构体的方式赋值,因此a这个主体会被parfor同时访问,因此不可行,而右侧没有使用结构体而是空数组,因此能被并行赋值,最后粘贴到结构体上去。
无效 | 有效 |
a.x = []; parfor idx = 1:10 a.x(idx) = 7; end | tmpx = []; parfor idx = 1:10 tmpx(idx) = 7; end a.x = tmpx; |
结构体矩阵的问题
Matlab推荐在并行计算的循环内构件结构体的临时变量,如下代码所示:
无效 | 有效 |
parfor i = 1:4 temp.myfield1 = rand(); temp.myfield2 = i; end | parfor i = 1:4 temp = struct(); temp.myfield1 = rand(); temp.myfield2 = i; End —- parfor i = 1:4 Temp= struct(‘myfield1′,rand(),’myfield2’,i); end |
在处理的过程中不使用结构体,处理结束后再生成:
无效 | 有效 |
parfor i = 1:4 outputData.outArray1(i) = 1/i; outputData.outArray2(i) = i^2; end | parfor i = 1:4 outArray1(i) = 1/i; outArray2(i) = i^2; end outputData = struct(‘outArray1′,outArray1,’outArray2’,outArray2); |
将带有结构体的代码片转换为函数处理也可以作为一种方法(演示代码略)。
不要使用如下的方式写语句
下列的代码片中有一个f(5)字眼,但很容易混淆是索引f数组的第五个元素或是对f()函数传入参数5,应尽量避免这种书写方式。
parfor i = 1:n
…
a = f(5);
…
End
不能在并行的过程中清除变量,但可以设置为空变量
无效 | 有效 |
parfor ii = 1:4 <statements…> clear(‘X’) % cannot clear: transparency violation <statements…> end | parfor ii = 1:4 <statements…> X = []; <statements…> end |