第二章:异步并行编程
使用parfeval,你可以在后台跑一个特定的功能函数并取出结果而不需要等待其完整跑完。在很多的情况下,提早从循环中释放代码继续运行下去是有利的,例如,对于一个优化的程序来说,就可以提前结束循环当确认了结果是足够好的,你可以在一个或者多个并行池上完成这个功能,请使用parfeval或者parfevalOnall。同样地,这对实时绘制图形也是有利的。请注意,这跟parfor是不一样的概念,因为parfor需要等待循环结束。
1.利用parfeval使函数在后台运行
这个示例用于展示你可以使用parfeval来在后台跑函数直到结果计算出来之后再获取。
先来看看parfeval的变量定义:
F = parfeval(P, FCN, NUMOUT, IN1, IN2, ...)
左侧F代表的是取未来的结果的意思,F会一直运行在后台获取并行计算的异步结果,如果要停止F工作,则必须键入cancel(F);
P是parallel pool并行计算核的意思,可以通过p = gcp()开启获得物理核心的使用权;
FCN是要跑的任务或函数;
NUMOUT是输出变量的个数;
IN1,IN2是FCN的输入参数;
下列代码段#1-1为Matlab的官方parfevel示例代码,第一行表明启动并行池并获得Matlab所获得的并行句柄(即现有的并行池资源信息),存放在变量p中;
4~7行开启一个循环计算任务,但注意,我们这次并没有使用parfor,而是只用了for字眼,然后,循环使用parfeval并将计算得到的结果存入f(idx)中,这里,f不是一个函数,是代表一个接收队列数组,不断存储parfeval计算完成后发过来的计算结果。在第6句中,parfeval的第一个参数输入p,代表获得现在的并行池信息并根据并行池数量进行分配任务,第二个参数是@magic,magic(x)代表生成x阶的魔方矩阵,前面加上@,代表传递这个函数作为使用,第三个参数1代表magic返回一个变量,这个变量可以是多维的,不要混淆,可以是这样:
Result = [1,2,3,4;5,6,7,8] 也是输出一个变量;
最后一个参数idx代表magic()的输入变量,实际意义为生成多少阶的魔方矩阵。
第10行代码创建一个元胞数组来获得计算得到的结果;
第11~16行通过循环获取计算的结果,若最新的结果没生成则会等待;completedIdx代表原来循环计算的压入f的索引号,value代表magic计算出来的结果,最后打印completedIdx观察计算结果的先后次序,请注意,有时候后面压入的计算可能会提早算了出来,排在前面获得结果,先后次序并不固定为idx的压入顺序,谁先算了出来,谁就被提早获得结果。
Code #1-1
1.p = gcp();
2.
3.% To request multiple evaluations, use a loop.
4.for idx = 1:10
5. % Square size determined by idx
6. f(idx) = parfeval(p,@magic,1,idx);
7.end
8.
9.% Collect the results as they become available.
10.magicResults = cell(1,10);
11.for idx = 1:10
12. % fetchNext blocks until next results are available.
13. [completedIdx,value] = fetchNext(f);
14. magicResults{completedIdx} = value;
15. fprintf('Got result with index: %d.\n', completedIdx);
16.end
如下是两次不同的计算结果次序,可以看到,有时候计算结果的顺序有先后,因此本章也称为异步编程,目的是为了让算好的先取出来用。