import ipyparallel as ipp
cluster = ipp.Cluster(engines="mpi", n=4)
# this could be set in your ipcluster_config.py as c.MPIEngine...
cluster.config.MPIEngineSetLauncher.environment = {"PYTHONHASHSEED": "1"}
cluster.start_cluster_sync()
rc = cluster.connect_client_sync()
rc.activate()
Starting 4 engines with <class 'ipyparallel.cluster.launcher.MPIEngineSetLauncher'>
<DirectView all>
%%px
import os
import random
print(f"hashseed: {os.environ['PYTHONHASHSEED']}")
print(f"hash: {hash('abc')}")
[stdout:0] hashseed: hash: -8758283693454389936
[stdout:1] hashseed: hash: 7726345156143226909
[stdout:2] hashseed: hash: -2044745521382537417
[stdout:3] hashseed: hash: -8296317318440886908
Launcher.output_file
is where the output is captured for subprocess launchers.
It cannot be set via configuration, but it can be specified if you launch engines separately:
import os
cluster = ipp.Cluster(engines="mpi", n=4)
cluster.start_controller_sync()
cluster.start_engines_sync(output_file=f"/tmp/engines-{os.getpid()}.log")
Starting 4 engines with <class 'ipyparallel.cluster.launcher.MPIEngineSetLauncher'>
'1648192308'
cluster.engine_set.output_file
'/tmp/engines-28200.log'
!tail {cluster.engine_set.output_file}
2022-03-25 08:11:49.817 [IPEngine.2] Running code in user namespace: a=5 2022-03-25 08:11:49.818 [IPEngine.2] WARNING | debugpy_stream undefined, debugging will not be enabled 2022-03-25 08:11:49.821 [IPEngine.0] Starting to monitor the heartbeat signal from the hub every 750 ms. 2022-03-25 08:11:49.824 [IPEngine.0] Completed registration with id 0 2022-03-25 08:11:49.834 [IPEngine.2] Starting to monitor the heartbeat signal from the hub every 750 ms. 2022-03-25 08:11:49.834 [IPEngine.1] Starting to monitor the heartbeat signal from the hub every 750 ms. 2022-03-25 08:11:49.835 [IPEngine.2] Completed registration with id 2 2022-03-25 08:11:49.835 [IPEngine.3] Starting to monitor the heartbeat signal from the hub every 750 ms. 2022-03-25 08:11:49.835 [IPEngine.1] Completed registration with id 1 2022-03-25 08:11:49.835 [IPEngine.3] Completed registration with id 3
Both of these can be accomplished with a custom launcher class that overrides the default environment and output file:
import os
import tempfile
from ipyparallel.cluster.launcher import MPIEngineSetLauncher
from traitlets import default
output_dir = tempfile.mkdtemp()
class CustomLauncher(MPIEngineSetLauncher):
@default("output_file")
def _default_output_dir(self):
return os.path.join(output_dir, f"{self.identifier}.log")
def get_env(self):
env = {}
# inherit these variables from the parent by default
for var in ["PYTHONHASHSEED"]:
if var in os.environ:
env[var] = os.environ[var]
env.update(super().get_env())
return env
os.environ["PYTHONHASHSEED"] = "12345"
with ipp.Cluster(engines=CustomLauncher, n=4) as rc:
hash_seeds = rc[:].apply_sync(os.getenv, "PYTHONHASHSEED")
print(f"engine output file: {rc.cluster.engine_set.output_file}")
print(f"hashseed: {hash_seeds}")
Starting 4 engines with <class '__main__.CustomLauncher'> 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [00:01<00:00, 2.93engine/s] engine output file: /var/folders/qr/3vxfnp1x2t1fw55dr288mphc0000gn/T/tmp0719m8_0/ipengine-1648193904-ix9w-1648193905-28200.log hashseed: ['12345', '12345', '12345', '12345'] Stopping engine(s): 1648193905 engine set stopped 1648193905: {'exit_code': 0, 'pid': 30966, 'identifier': 'ipengine-1648193904-ix9w-1648193905-28200'} Stopping controller Controller stopped: {'exit_code': 0, 'pid': 30952, 'identifier': 'ipcontroller-1648193904-ix9w-28200'}