How to properly Abort from within a ParallelMap?

If a condition is met within a sub-kernel in the function being mapped, how does one cancel the whole ParallelMap operation?

ParallelMap[
Check[Pause[1];
If[# > 10, Print[$$KernelID, " failed on ", #];$$Failed,
Print[$KernelID, " suceeded on ", #]], AbortKernels[]] &, Range[20]]  This seems like something commonplace, but I can't remember how or find it anywhere in the docs! • Looks like you want ParallelTry – Lukas Lang Mar 8 at 12:31 • It’s sort of the opposite - ParallelTry returns the first successful result, I want to stop on the first failure – M.R. Mar 8 at 12:37 1 Answer Adapting the code from ParallelTry to do what you need, we get ComputeUntilFailure[f_, _[args___]] := Module[ {ids, id, r, res = <||>}, DistributeDefinitions[{f, args}]; ids = List @@ ParallelSubmit /@ (# -> f@# &) /@ Hold[args]; While[Length@ids > 0, {r, id, ids} = WaitNext[ids]; If[FailureQ@Last@r, AbortKernels[]; Clear@ids; Break[], AppendTo[res, r] ] ]; res ]  Basically, this uses ParallelSubmit to launch the computations on parallel kernels. The results are then processed one by one on the main kernel using WaitNext, until one of them is a failure, at which point we abort the remaining computations. Applying this to the example given in the question: ComputeUntilFailure[ ( Pause@1; If[# > 10, Print[$$KernelID, " failed on ", #];$$Failed, Print[$KernelID, " succeeded on ", #]
]
) &,
Range[20]
]
(* 6 succeeded on 1 *)
(* 5 succeeded on 2 *)
(* 4 succeeded on 3 *)
(* 3 succeeded on 4 *)
(* 2 succeeded on 5 *)
(* 1 succeeded on 6 *)
(* 6 succeeded on 7 *)
(* 5 succeeded on 8 *)
(* 4 succeeded on 9 *)
(* 3 succeeded on 10 *)
(* 2 failed on 11 *)
(* 1 failed on 12 *)
(* <|1 -> Null, 2 -> Null, 3 -> Null, 4 -> Null, 5 -> Null,
6 -> Null, 7 -> Null, 8 -> Null, 9 -> Null, 10 -> Null|> *)

• Thanks, can you give an example usage of this? – M.R. Mar 8 at 22:17
• I'm wondering why does it not abort after it fails on 11? – M.R. Mar 12 at 15:52
• @M.R. The issue is that all the tasks finish almost exactly simultaneously. So when the main thread got the first failed result from Kernel 2, Kernel 1 also produces a failed result (almost) the same instant, before the main kernel has any chance to abort the computation. If you replace the Pause[1] statement with Pause@RandomReal[] (to force the different kernels to be less synchronous), it will only generate a single failed result in most cases. – Lukas Lang Mar 12 at 16:51
• Interesting, I’d consider that a bug in the parallel functions – M.R. Mar 12 at 17:45
• @M.R. why? I would say that that's just the nature of concurrent programs (If you want to avoid that things finish simultaneously, you can simply remove the parellization ;-) ) Also, note that the returned list contains neither of the two failed instances, as expected – Lukas Lang Mar 12 at 18:05