5
$\begingroup$

I've noticed that I can't Throw from within a ParallelDo in the same way that I can from inside Do. For instance, the following will work as anticipated with Do but not with ParallelDo:

Catch[ParallelDo[num=RandomInteger[{1,5}];Print[num];If[num==2,Throw[i]],{i,10}]]

It generates errors of the following form:

Throw::nocatch: Uncaught Throw[7] returned to top level.

ParallelDeveloperQueueRun::hmm: Received unexpected result Hold[Throw[7]] from KernelObject[4,local].

As I read it, the Catch isn't passed to the servant kernels, so when the servant kernels try to Throw, they get confused. Meanwhile, the main kernel just receives a Throw[i] and doesn't know how to evaluate it.

Is there any way to have the servant kernels just serve the results no matter what and have the main kernel check the Catch/Throw?

I could probably emulate this by having the servant kernels running Abort in place of Throw, but this feels more like a hack.

This is not unrelated to the problem discussed here, but I only need to return a specific result (the one that I'd like to trigger Throw) rather than all results calculated so far, and I'm working with ParallelDo instead of Table, which I think means it's safely interruptible anyway (see David's answer to the linked question using Abort).

$\endgroup$
6
$\begingroup$

If the goal is to perform a parallel search for the first result that meets some condition, then we can consider using ParallelTry instead of throw/catch:

ParallelTry[If[PrimeQ[#], #, $Failed]&, Range[492114, 500000]]

(* 492227 *)

This evaluates a function for every value in the second argument (in parallel). The first result that is anything other than $Failed is returned immediately, and all other parallel computations are quietly aborted.

If all evaluations fail, a warning is issued along with the result $Failed:

ParallelTry[If[PrimeQ[#], #, $Failed]&, Range[492114, 492226]]

(* ParallelTry::toofew: Only 0 results received, rather than 1. >>
   $Failed *)

We can also ask for more than one result to be returned:

ParallelTry[If[PrimeQ[#], #, $Failed]&, Range[492113, 500000], 2]

(* {492113,492227} *)
$\endgroup$
  • $\begingroup$ Thanks -- I'm playing with this approach. The difficulty is that I define several auxiliary variables on each try, so I think I'll need to restructure somewhat, but it should probably work (and it might even be more efficient). $\endgroup$ – Shane Mar 24 '15 at 17:59
2
$\begingroup$

Similar to my answer to this question you probably have to redesign your code. Depending on your need

Module[{counter = 1},
 ParallelDo[
  While[2 != (num = RandomInteger[{1, 15}]) && counter <= 10, counter++; Print[num]];
  If[counter <= 10, Print["Thrown at trial " <> ToString[counter]]], {$ProcessorCount}]]

or

Module[{counter = 1},
 ParallelTry[
  While[2 != (num = RandomInteger[{1, 15}]) && counter <= 10, counter++; Print[num]];
  If[counter <= 10, Print["Thrown at trial " <> ToString[counter]]], {$ProcessorCount}]];

should work. The first one returning as many results as ProcessorCount and the second one only returning the result first found.

$\endgroup$
  • $\begingroup$ Looking at the second one, is the counter being shared across the servant kernels or does each servant have its own? If the former, I can probably use Monitor to track it. I'm not sure about the latter. $\endgroup$ – Shane Mar 24 '15 at 18:08
  • $\begingroup$ Each kernel has its own counter. It is not shared. $\endgroup$ – Karsten 7. Mar 24 '15 at 18:10
  • $\begingroup$ @Shane If you want to use Monitor, you can remove the Module, set counter = 0; as a global variable and share it among the kernels by executing SetSharedVariable[counter]. Now Monitor will work. $\endgroup$ – Karsten 7. Mar 24 '15 at 18:21
  • $\begingroup$ Thanks - that's what I had in mind also. I guess having local counters minimizes the communication to make it more efficient, but it's also nice to have the global counter. I'm testing this solution and WReach's. $\endgroup$ – Shane Mar 24 '15 at 18:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.