Skip to content
Snippets Groups Projects
Commit 216af2fa authored by Axel von Arnim's avatar Axel von Arnim Committed by BBP code review
Browse files

Merge "[NRRPLT-5486] Support multi-process RNG seed."

parents c2242850 d3f61316
No related branches found
No related tags found
No related merge requests found
......@@ -24,6 +24,7 @@
"""
A distributed brain process that can be launched standalone on remote hosts.
"""
from hbp_nrp_cle.brainsim import config
from hbp_nrp_cle.brainsim.pynn import simulator as sim
from hbp_nrp_cle.brainsim.pynn.PyNNControlAdapter import PyNNControlAdapter
import hbp_nrp_cle.tf_framework.config as tf_config
......@@ -51,7 +52,7 @@ class MUSICBrainProcess(object):
# tag to listen for MPI configuration/command messages
MPI_MSG_TAG = 100
def __init__(self, bibi_file):
def __init__(self, bibi_file, rng_seed):
"""
Load the distributed brain and construct MUSIC proxies for communication
to/from the CLE. Nest will automatically allocate the brain in a round-robin
......@@ -74,6 +75,9 @@ class MUSICBrainProcess(object):
"defined on target node!")
brain_file = os.path.join(models_path, self._bibi.brainModel.file)
# set the RNG seed before initializing any PyNN interfaces in the brain controller
config.rng_seed = int(rng_seed)
# spawn CLE components that will handle loading the brain file and interfaces
self._brain_controller = PyNNControlAdapter()
self._brain_controller.initialize()
......@@ -195,10 +199,12 @@ if __name__ == '__main__': # pragma: no cover
parser = argparse.ArgumentParser()
parser.add_argument('--bibi-file', dest='bibi_file',
help='the bibi file path to load', required=True)
parser.add_argument('--rng-seed', dest='rng_seed',
help='the global experiment RNG seed', required=True)
args = parser.parse_args()
# construct brain and proxies (expand environment variables in paths)
brain = MUSICBrainProcess(os.path.expandvars(args.bibi_file))
brain = MUSICBrainProcess(os.path.expandvars(args.bibi_file), args.rng_seed)
# run the brain until terminated, this is a blocking call
brain.run()
......
......@@ -31,6 +31,8 @@ from hbp_nrp_music_interface.launch.host.LocalLauncher import LocalLauncher
from hbp_nrp_music_interface.launch.host.LuganoLauncher import LuganoLauncher
import os
import random
import sys
class MUSICLauncher(object):
......@@ -78,20 +80,22 @@ class MUSICLauncher(object):
# the MPI process launcher for the CLE and brain processes
self.cle_server = None
def init(self, bibi, brain_processes):
def init(self, bibi, exd):
"""
Construct the MUSIC launch configuration that will spawn CLE + brain processes
on distributed hosts.
:param bibi The BIBI configuration to launch brain processes with.
:param brain_processes The number of brain processses (does not include CLE process).
:param exd The parsed ExDConf configuration to launch brain processes with.
"""
# create a host specific launcher
if self._server_host == 'local':
self._launcher = LocalLauncher()
elif self._server_host == 'lugano':
self._launcher = LuganoLauncher(brain_processes + 1, self._timeout, self._reservation)
self._launcher = LuganoLauncher(exd.bibiConf.processes + 1,
self._timeout,
self._reservation)
else:
raise Exception('Unknown server host {}, cannot configure and launch MUSIC!'
.format(self._server_host))
......@@ -104,6 +108,9 @@ class MUSICLauncher(object):
reservation_str = self._reservation if self._reservation else ''
timeout_str = str(self._timeout).replace(' ', '_')
# extract the multiprocess RNG seed to use or generate one if needed
rng_seed = exd.rngSeed if exd.rngSeed is not None else random.randint(1, sys.maxint)
# build a MUSIC configuration script with correct brain ports, launchers and arugments
# save it to the host launcher temp directory, this is the same for every host
music_conf = bibi_music_config.MUSICConfiguration(bibi)
......@@ -116,12 +123,14 @@ class MUSICLauncher(object):
'--reservation={}'.format(reservation_str),
'--sim-id={}'.format(self._sim_id),
'--timeout={}'.format(timeout_str),
'--rng-seed={}'.format(rng_seed),
'--music'],
1)
music_conf.add_application('BRAIN',
brain_launcher,
['--bibi-file={}'.format(self._bibi_file)],
brain_processes)
['--bibi-file={}'.format(self._bibi_file),
'--rng-seed={}'.format(rng_seed)],
exd.bibiConf.processes)
music_conf.save(self._launcher.local_tmpdir)
# deploy the generated configuration files / launch scripts to the target host
......@@ -132,7 +141,7 @@ class MUSICLauncher(object):
self.cle_server = MUSICMPILauncher()
self.cle_server.add_host(self._launcher.hostname,
self._launcher.host_tmpdir,
brain_processes + 1)
exd.bibiConf.processes + 1)
# construct the mpi command line with the above host/launch information
self.cle_server.build()
......
......@@ -59,8 +59,13 @@ class TestMUSICLauncher(unittest.TestCase):
@patch('hbp_nrp_music_interface.launch.MUSICLauncher.MUSICMPILauncher')
def test_init(self, mock_mpi, mock_conf):
# mock the ExDConf and parameters
exd = Mock()
exd.rngSeed = 123456
exd.bibiConf.processes = 10
# mock all of the local launcher functionality
self.__launcher.init('bibi', 10)
self.__launcher.init('bibi', exd)
# call to generate launch scripts
self.__launcher._launcher.deploy.assert_called_once()
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment