本文主要以并行语句parfor为例进行探索。
1. 适用条件
(1)每次循环之间是相互独立的;
(2)循环执行完之后的结果和循环执行的先后次序无关;
(3)不适用于频繁读写内存的算法。
2. 设置并行环境
%% 设置并行计算环境
poolobj = gcp('nocreate');
if isempty(poolobj)
poolsize = 0;
CoreNum = 4; % 设置CPU核心数量
parpool('local', CoreNum);
else
poolsize = poolobj.NumWorkers;
disp('Already initialized'); % 并行环境已启动
end
%% 关闭并行计算环境
delete(gcp('nocreate'));
如果长时间不运行并行计算,计算机会在30min后关闭并行环境。
3. 简单实例
clc;clear all;
tic
a = zeros(10000,10000); % 先分配内存
core_number = 4; % 想要调用的处理器个数
parpool('local',core_number);
parfor i = 1:10000
for j = 1:10000
a(i,j) = i*j;
end
disp(i)
end
toc
delete(gcp('nocreate'));
如果不预先分配内存、不使用parfor的条件下,在我的笔记本上运行此程序大约需要390s;仅使用parfor,不预先分配内存,运行此程序大约需要23s;如果预先分配好内存,运行此程序仅需1.8s,此时就显示不出parfor的作用了,所以在运行大数组之前一定要提前分配好内存~
4. 注意事项
4.1 parfor-Loop中的变量应该为连续增加的整数
以下是三种反例:
parfor ii = 0:0.2:1 % 不是整数
parfor jj = 1:2:11 % 不是连续整数
parfor kk = 10:-1:1 % 不是递增整数
如果需要引用上述变量,可以参考如下方式进行修改:
ii = 0:0.2:1;
parfor id_ii = 1:numel(ii)
iii = ii(id_ii);
...
end
4.2 parfor-Loop中的变量分类问题
parfor-Loop中的变量包括如下5个分类:
分类
描述循环变量
parfor的循环索引
切片变量
需要读取或写入的parfor之外的变量,且读取或写入位置与循环变量相关,每次循环中只能读取由同一个索引值索引的切片,如 a[i] 和 a[i+1] 同时出现,则a不被识别为切片变量
广播变量
在循环之前定义好的变量,在循环内部只需读取即可
简约变量
可在多次循环内对一个变量操作,该变量与迭代顺序无关
临时变量
在循环内部创建,循环结束后会清除调,但不在循环外部访问a = 0;
c = pi;
z = 0;
r = rand(1,10)
parfor k = 1 : 100 % k为循环变量
a = k; % a为临时变量
z = z + k; % z为简约变量
b(k) = r(k); % r为切片变量(输入),b为切片变量(输出)
if k <= c % c为广播变量
d = 2 * a; % d为临时变量
end
end
(1)在parfor-Loop中,如果使用嵌套的for循环来索引切片数组,则不能在parfor循环的其他地方再次使用该数组。举例如下:
%% 无效代码,因为数组A是在嵌套的for循环中被切片和索引的
A = zeros(4,10);
parfor i = 1:4
for j = 1:10
A(i,j) = i + j;
end
disp(A(i,1))
end
%% 有效代码,v被分配到了嵌套循环的外部
A = zeros(4,10);
parfor i = 1:4
v = zeros(1,10);
for j = 1:10
v(j) = i + j;
end
disp(v(1))
A(i,:) = v;
end
(2)
参考:
【1】MATLAB官方帮助文档。