MMA有个asynchronous computing的功能叫ParallelSubmit
它不仅可以配合WaitAll/WaitNext做异步运算,还附赠精美status icon来提示工作状态
基本上它的icon有4种state
1. Ready : work item在queue中等待
2. Running : 送到parallel kernel中正在跑...
3. Received/Finished : 跑完了已经回传output到主kernel
4. Failed : 这个work item GG惹 (通常是因为AbortKernels[])
最后的Failed很怪, 如果乖乖在item里送出Abort就只是终止这个item并回传$Aborted
由于这个item还是正常地完成了, status icon会辨识为Received/Finished而非直觉上的
Failed
要跳到Failed state一定得要从MMA的asynchronous queue本身下手才有用
例如用 Parallel`Developer`ResetQueues直接把queue中的ready states清空
或是在WaitNext/WaitAll执行work item的过程中直接在front end abort
也就是说这个Failed state基本上没用OTZ
为了增加它的用途我用doc里提到的"重复跑同一个work item两次会跳到Failed state"的
特性做了一个可以自动在遇到$Failed或$Aborted时跳到Failed state的WaitAll
除此之外它也可以吃{$Failed/$Aborted, failed expression} 来提供CheckAbort的功能
(bag只是个container,不想有shadowing的话可以再包一层)
WaitAllBetter[F : {__EvaluationObject}] :=
CheckAbort[Block[{res = bag[], obj, queue = F, temp, out, Stepper},
Stepper = ({temp, obj, queue} = WaitNext[#];
res = {res, bag[temp]};
If[MemberQ[{$Failed, $Aborted}, #] & /@
Or[temp, Quiet@temp[[1]]], WaitAll[obj]];) &;
Do[Stepper[queue], {Length[F]}];
Flatten@res /. bag -> Sequence /. {$Failed | $Aborted, out_} ->
out], AbortKernels[]; Abort[]]
用这个function可以实作TimeConstraint的同时避免掉用Message产生洗版的问题
以ParallelSubmit MMA doc的Neat example为例
(PrintTemporary[#]; #) &@
Table[ParallelSubmit[{i}, If[# === $Aborted, {$Failed, TO[i]}, #] &@
TimeConstrained[Plus @@ FactorInteger[2^i - 1][[All, 2]], 4]],
{i, 220, 170, -1}];
WaitAllBetter[%]
跑起来比Message清楚多了~