8

Is it possible to register a some "initialization code" to be run on any newly started parallel kernel?

This would be similar to how ParallelNeeds registers a package to be loaded right away when a new kernel is started, or how DistributeDefinitions and SetSharedVariable/SetSharedFunction take effect immediately on a newly launched subkernel.

Why do I need this?

Mainly to make sure that certain global settings are set. Examples: $Path, $Assumptions, $MaxExtraPrecision, etc. The biggest reason is really $Path.

Note that kernels may get launched automatically, even during ongoing computations. When a kernel dies unexpectedly, it will be re-launched.

Related:

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263

1 Answers1

10

I found two ways to do this. Both are undocumented, so all usual caveats apply.

Parallel`Developer`$InitCode

This can be done using Parallel`Developer`$InitCode. While undocumented, this does appear fairly stable.

First trigger loading the parallel tools:

Parallelize;

?Parallel`Developer`$InitCode

ReleaseHold[$InitCode] is run on every new subkernel for user initialization.

Just set

Parallel`Developer`$InitCode = Hold[your; code; here]

One problem with this is that it will be run only after packages registered by ParallelNeeds are loaded. Thus it cannot be used to set the $Path.

Parallel`Protected`AddInitCode

The following is a hack messing with the internals of the parallel tools package. Use at your own risk. The advantage is that it can be used to set $Path, to be used with ParallelNeeds.

Parallelize; (* trigger loading *)

?Parallel`Protected`AddInitCode

AddInitCode[code] sends code to running subkernels and uses AppendInitCode to remember it.

?Parallel`Protected`AppendInitCode

AppendInitCode[code] is for load-time setup of init code.

Register code to be run at kernel startup like this:

Parallel`Protected`AddInitCode[
 Parallel`Client`HoldCompound[your; code; here],
 True (* permanent *)
]

The second argument controls whether this init code should survive Parallel`Developer`ClearKernels[]. This argument can be omitted and defaults to False.

This is the same mechanism that ParallelNeeds uses. Make sure to register the $Path change before evaluating ParallelNeeds.

SetSharedVariable/SetSharedFunction also make use of AddInitCode.

These initialization code will be registered in the following variables:

Parallel`Kernels`Private`$clientCode
Parallel`Kernels`Private`$clientOriginalCode

$clientOriginalCode contains code set to persist even after ClearKernels[]. $clientCode contains all init code, both persistent and not.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263