4
$\begingroup$

Is there a way to evaluate some expression in a subsession of another already running kernel, collecting the output, from a Local monitoring kernel? Something like

result1 = EvaluateInSubsession[expr1, kernel1]
result2 = EvaluateInSubsession[expr2, kernel2]

Added in clarification. This is useful while running independent computations in different kernels, and one would like to collect some monitoring information from them. The idea is to automate what one would do by evaluating in subsession within separate notebook frontends.

Something can indeed be done manually or via the frontend tokens: I added below a possible solution, not entirely satisfactory.

The perfect solution would instead be if one could enter a subsession programmatically, something like

CurrentValue[nb, Evaluator] = kernel1;
NotebookEvaluate[nb, Method->"Subsession"]       <------- ☹️
$\endgroup$
2
  • 1
    $\begingroup$ Thanks for the comment - Well, yes, I did some extensive search. I was not searching for parallel kernel evaluation, the kernels are already running, normal ones... Sorry if the question is badly formulated.... In fact the question is similar to this mathematica.stackexchange.com/questions/178784/… and we see that it was not easy. However, in that case one has to hack a cell evaluator... something that can be only done in frontend... $\endgroup$ Commented Jan 22, 2023 at 14:39
  • $\begingroup$ (see also this, with mathlink mathematica.stackexchange.com/a/14176/90094 ) $\endgroup$ Commented Jan 26, 2023 at 19:01

3 Answers 3

3
$\begingroup$

Ok, one possible solution. Apparently the only way to enter a subsession programmatically is to use the frontend, via the token "SubsessionEvaluateCells". Therefore the input must be put in some cell in a visible notebook. The solution below opens and builds a new notebook, evaluates in subsession, waits for the result and closes the notebook. Quite kludgy - hopefully it could be done better...🤨

SetAttributes[EvaluateInSubsession, HoldFirst]
EvaluateInSubsession[expr_, kernel_] := Block[{nb, r},
  nb = CreateDocument[{ExpressionCell[Defer[expr], "Input"]}, Visible -> True];
  SelectionMove[nb, After, CellContents];
  NotebookWrite[nb, "\n\"DONE\""];
  CurrentValue[nb, Evaluator] = kernel;
  FrontEndTokenExecute["SubsessionEvaluateCells"];
  FrontEndTokenExecute["WindowMiniaturize"];
  Until[r == "\"DONE\"", Pause[.1];
   SelectionMove[nb, After, Notebook]; 
   SelectionMove[nb, Previous, CellContents]; r = NotebookRead[nb]];
  SelectionMove[nb, After, Notebook]; 
  SelectionMove[nb, Previous, CellContents, 2];
  r = NotebookRead[nb] // ToExpression;
  NotebookClose[nb];
  If[r =!= "DONE", Return[r]];
  ]

Usage e.g.: EvaluateInSubsession[ Plot[f[x], {x, -4, 4}], "Local2"]

(note WindowMiniaturize to avoid messing with the nb selected cells)

$\endgroup$
3
$\begingroup$

Does the following do what you want:

SetAttributes[EvaluateInSubsession, HoldFirst]
EvaluateInSubsession[x_,kernel_] := Module[{cell},
    cell = PrintTemporary[Dynamic[x, Evaluator->kernel]];
    FrontEndExecute @ FrontEnd`NotebookDynamicToLiteral @ cell;
    ToExpression @ Extract[{1,1}] @ NotebookRead @ cell
]

For example, in the kernel "Local 2" x has the value 3.

x

EvaluateInSubsession[Plot[Sin[y], {y, 0, x}], "Local 2"]

x

enter image description here

$\endgroup$
3
  • $\begingroup$ Very nice, silent, and also great to learn the use of NotebookDynamicToLiteral! However I see two issues here : 1- in case the computation is slow I am not sure what happens.. 2- the computation seems to be evaluated (at least) twice? EvaluateInSubsession[(Pause[1]; ++aa), "Local2"] prints 3, instead of 2 (aa was 1, before) Uhm $\endgroup$ Commented Jan 26, 2023 at 9:21
  • $\begingroup$ DynamicEvaluationTimeout->Infinity helps for the first issue $\endgroup$ Commented Jan 26, 2023 at 9:55
  • $\begingroup$ And finally this seems to work for the second issue: TrackedSymbols :> {}, the expression is evaluated only once at the beginning of Dynamic. So altogether Style[Dynamic[x, TrackedSymbols :> {}, Evaluator -> kernel], DynamicEvaluationTimeout -> Infinity] solves everything. If you want you can update your answer - or I can make a new one. Thanks. $\endgroup$ Commented Jan 26, 2023 at 11:14
1
$\begingroup$

So, this is the refined answer, based on the previous one by Carl Woll. It is now robust wrt to long evaluations and evaluates expr only once.

SetAttributes[EvaluateInSubsession, HoldFirst]
EvaluateInSubsession[expr_, kernel_] := 
 Module[{cell}, 
  cell = PrintTemporary[
    Style[Dynamic[expr, TrackedSymbols :> {}, Evaluator -> kernel], DynamicEvaluationTimeout -> Infinity]];
  FrontEndExecute @ FrontEnd`NotebookDynamicToLiteral @ cell;
  ToExpression @ Extract[{1, 1}] @ NotebookRead @ cell]

(still minor issues - the frontend freezes during computation and grays out until completion if the computation takes more than 10 seconds - and it can not be parallelized, if one has more kernels to interrogate (PrintTemporary does not parallelize))

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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