diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 58e58a0c83c56477665fd3f1ebe15c66c04d0799..5fc85d2d94c97ca3f9474ba7707bc04a75c01f2a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,11 +7,31 @@ default:
     expire_in: 3 days
 
 stages:
-  - generate
+  - initialize
   - process
   - collect
   - finish
 
+detector:
+  stage: initialize
+  needs: []
+  timeout: 1 hours
+  cache:
+    key:
+      files:
+        - config/env.sh
+        - util/build_detector.sh
+      prefix: "$CI_COMMIT_REF_SLUG"
+    paths:
+      - .local/detector
+      - .local/lib
+  artifacts:
+    paths:
+      - .local/detector
+      - .local/lib
+  script:
+    - ./util/build_detector.sh
+
 include:
   - local: 'dis/config.yml'
   - local: 'dvmp/config.yml'
diff --git a/config/env.sh b/config/env.sh
index 73aaf5981f656dfcd19cbf5fead712e88a35b27d..5abe41947886239dabd08153fe89e1353e1d26fa 100755
--- a/config/env.sh
+++ b/config/env.sh
@@ -8,6 +8,8 @@
 ##  - JUGGLER_DETECTOR:       detector package to be used for the benchmark
 ##  - JUGGLER_N_EVENTS:       #events processed by simulation/reconstruction
 ##  - JUGGLER_INSTALL_PREFIX: location where Juggler (digi/recon) is installed
+##  - JUGGLER_N_THREADS:      Number of threads/processes to spawn in parallel
+##  - JUGGLER_RNG_SEED:       Random seed for the RNG
 ##
 ## It also defines the following additional variables for internal usage
 ##  - LOCAL_PREFIX:           prefix for packages installed during the benchmark
@@ -38,6 +40,22 @@ if [ ! -n  "${JUGGLER_N_EVENTS}" ] ; then
 fi
 echo "JUGGLER_N_EVENTS:       ${JUGGLER_N_EVENTS}"
 
+## Maximum number of threads or processes a single pipeline should use
+## (this is not enforced, but the different pipeline scripts should use
+##  this to guide the number of parallel processes or threads they 
+##  spawn).
+if [ ! -n "${JUGGLER_N_THREADS}" ]; then
+  export JUGGLER_N_THREADS=10
+fi
+echo "JUGGLER_N_THREADS:      ${JUGGLER_N_THREADS}"
+
+## Random seed for event generation, should typically not be changed for
+## reproductability.
+if [ ! -n "${JUGGLER_RNG_SEED}" ]; then
+  export JUGGLER_RNG_SEED=1
+fi
+echo "JUGGLER_RNG_SEED:       ${JUGGLER_RNG_SEED}"
+
 ## Install prefix for juggler, needed to locate the Juggler xenv files.
 ## Also used by the CI as install prefix for other packages where needed.
 ## You should not have to touch this. Note that for local usage a different 
diff --git a/dis/scripts/rec_dis_electrons.cxx b/dis/analysis/rec_dis_electrons.cxx
similarity index 100%
rename from dis/scripts/rec_dis_electrons.cxx
rename to dis/analysis/rec_dis_electrons.cxx
diff --git a/dis/config.yml b/dis/config.yml
index c0dda0dc156b2ce3861891eb91dd3f9f694c6d22..957da8fa851632e28ba534541568bb910ef27949 100644
--- a/dis/config.yml
+++ b/dis/config.yml
@@ -1,11 +1,25 @@
-dis:run_test:
-  stage: process
+dis:generate:
+  stage: initialize
+  needs: []
   timeout: 1 hours
+  artifacts:
+    paths:
+      - results
+  script:
+    - bash dis/gen.sh
+
+dis:process:
+  stage: process
+  needs: ["detector", "dis:generate"]
+  timeout: 1 hour
+  artifacts:
+    paths:
+      - results
   script:
-    - bash dis/dis.sh
+    - echo "DIS benchmarks"
 
 dis:results:
   stage: collect
-  needs: ["dis:run_test"]
+  needs: ["dis:process"]
   script:
     - echo "All DIS benchmarks successful"
diff --git a/dis/dis.sh b/dis/dis.sh
index 8bdaffbd8a81df4489fbc4183b1b9767a3c99225..171c792a4e6388b9942bd4df01b43114a2d6193f 100644
--- a/dis/dis.sh
+++ b/dis/dis.sh
@@ -1,82 +1,99 @@
 #!/bin/bash
 
-if [[ ! -n  "${JUGGLER_DETECTOR}" ]] ; then 
-  export JUGGLER_DETECTOR="topside"
-fi
-
-if [[ ! -n  "${JUGGLER_N_EVENTS}" ]] ; then 
-  export JUGGLER_N_EVENTS=100
-fi
-
-if [[ ! -n  "${JUGGLER_INSTALL_PREFIX}" ]] ; then 
-  export JUGGLER_INSTALL_PREFIX="/usr/local"
-fi
-
-export JUGGLER_FILE_NAME_TAG="dis"
-export JUGGLER_GEN_FILE="${JUGGLER_FILE_NAME_TAG}.hepmc"
-
+## =============================================================================
+## Run the DVMP benchmarks in 5 steps:
+## 1. Build/install detector package
+## 2. Detector simulation through npsim
+## 3. Digitization and reconstruction through Juggler
+## 4. Root-based Physics analyses
+## 5. Finalize
+## =============================================================================
+
+echo "Running the DIS benchmarks"
+
+## make sure we launch this script from the project root directory
+PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/..
+pushd ${PROJECT_ROOT}
+
+## =============================================================================
+## Load the environment variables. To build the detector we need the following
+## variables:
+##
+## - JUGGLER_INSTALL_PREFIX: Install prefix for Juggler (simu/recon)
+## - JUGGLER_DETECTOR:       the detector package we want to use for this benchmark
+## - DETECTOR_PATH:          full path to the detector definitions
+##
+## You can ready config/env.sh for more in-depth explanations of the variables
+## and how they can be controlled.
+source config/env.sh
+
+## Extra environment variables for DVMP:
+## file tag for these tests
+JUGGLER_FILE_NAME_TAG="dis"
+# TODO use the input file name, as we will be generating a lot of these
+# in the future...
+# FIXME Generator file hardcoded for now
+## note: these variables need to be exported to be accessible from
+##       the juggler options.py. We should really work on a dedicated
+##       juggler launcher to get rid of these "magic" variables. FIXME
+export JUGGLER_GEN_FILE="results/dis/${JUGGLER_FILE_NAME_TAG}.hepmc"
 export JUGGLER_SIM_FILE="sim_${JUGGLER_FILE_NAME_TAG}.root"
 export JUGGLER_REC_FILE="rec_${JUGGLER_FILE_NAME_TAG}.root"
 
-echo "JUGGLER_N_EVENTS = ${JUGGLER_N_EVENTS}"
-echo "JUGGLER_DETECTOR = ${JUGGLER_DETECTOR}"
-
-
-### Build the detector constructors.
-git clone https://eicweb.phy.anl.gov/EIC/detectors/${JUGGLER_DETECTOR}.git
-git clone https://eicweb.phy.anl.gov/EIC/detectors/accelerator.git
-pushd ${JUGGLER_DETECTOR}
-ln -s ../accelerator/eic
-popd
-mkdir ${JUGGLER_DETECTOR}/build
-pushd ${JUGGLER_DETECTOR}/build
-cmake ../. -DCMAKE_INSTALL_PREFIX=/usr/local && make -j30 install
-popd
 
-# generate the input events
-# temporary standin until hepmc output from pythia is generated.
-root -b -q "dis/scripts/gen_central_electrons.cxx(${JUGGLER_N_EVENTS}, \"${JUGGLER_FILE_NAME_TAG}.hepmc\")"
-if [[ "$?" -ne "0" ]] ; then
-  echo "ERROR running script"
-  exit 1
-fi
+## =============================================================================
+## Step 1: Build/install the desired detector package
+## TODO remove this
+#bash util/build_detector.sh
 
-#
-pushd ${JUGGLER_DETECTOR}
-
-## run geant4 simulations
+## =============================================================================
+## Step 2: Run the simulation
+echo "Running Geant4 simulation"
 npsim --runType batch \
       --part.minimalKineticEnergy 1000*GeV  \
       -v WARNING \
       --numberOfEvents ${JUGGLER_N_EVENTS} \
-      --compactFile ${JUGGLER_DETECTOR}.xml \
-      --inputFiles ../${JUGGLER_FILE_NAME_TAG}.hepmc \
-      --outputFile  ${JUGGLER_SIM_FILE}
-if [[ "$?" -ne "0" ]] ; then
-  echo "ERROR running script"
+      --compactFile ${DETECTOR_PATH}/${JUGGLER_DETECTOR}.xml \
+      --inputFiles ${JUGGLER_GEN_FILE} \
+      --outputFile ${JUGGLER_SIM_FILE}
+if [ "$?" -ne "0" ] ; then
+  echo "ERROR running npsim"
   exit 1
 fi
 
-# Need to figure out how to pass file name to juggler from the commandline
+## =============================================================================
+## Step 3: Run digitization & reconstruction
+echo "Running the digitization and reconstruction"
+# FIXME Need to figure out how to pass file name to juggler from the commandline
 xenv -x ${JUGGLER_INSTALL_PREFIX}/Juggler.xenv \
-  gaudirun.py ../options/tracker_reconstruction.py
-if [[ "$?" -ne "0" ]] ; then
+  gaudirun.py options/tracker_reconstruction.py
+if [ "$?" -ne "0" ] ; then
   echo "ERROR running juggler"
   exit 1
 fi
 ls -l
-popd
-
-pwd
-mkdir -p results/dis
 
-root -b -q "dis/scripts/rec_dis_electrons.cxx(\"${JUGGLER_DETECTOR}/${JUGGLER_REC_FILE}\")"
+## =============================================================================
+## Step 4: Analysis
+root -b -q "dis/analysis/rec_dis_electrons.cxx(\"${JUGGLER_DETECTOR}/${JUGGLER_REC_FILE}\")"
 if [[ "$?" -ne "0" ]] ; then
   echo "ERROR running root script"
   exit 1
 fi
 
-if [[ "${JUGGLER_N_EVENTS}" -lt "500" ]] ; then 
-cp ${JUGGLER_DETECTOR}/${JUGGLER_REC_FILE} results/dis/.
+## =============================================================================
+## Step 5: finalize
+echo "Finalizing ${JUGGLER_FILE_NAME_TAG} benchmark"
+
+## Copy over reconsturction artifacts as long as we don't have
+## too many events
+if [ "${JUGGLER_N_EVENTS}" -lt "500" ] ; then 
+  cp ${JUGGLER_REC_FILE} results/dis/.
 fi
 
+## cleanup output files
+rm ${JUGGLER_REC_FILE} ${JUGGLER_SIM_FILE}
+
+## =============================================================================
+## All done!
+echo "${JUGGLER_FILE_NAME_TAG} benchmarks complete"
diff --git a/dis/gen.sh b/dis/gen.sh
new file mode 100644
index 0000000000000000000000000000000000000000..5a4c4aeb0b0a71fe277e12fd26a294433d719d4f
--- /dev/null
+++ b/dis/gen.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+## =============================================================================
+## Standin for a proper pythia generation process, similar to how we
+## generate events for DVMP
+## =============================================================================
+
+## TODO: use JUGGLER_FILE_NAME_TAG instead of explicitly refering to dis
+
+echo "Running the DIS benchmarks"
+
+## make sure we launch this script from the project root directory
+PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/..
+pushd ${PROJECT_ROOT}
+
+## =============================================================================
+## Load the environment variables. To build the detector we need the following
+## variables:
+##
+## - JUGGLER_INSTALL_PREFIX: Install prefix for Juggler (simu/recon)
+## - JUGGLER_DETECTOR:       the detector package we want to use for this benchmark
+## - DETECTOR_PATH:          full path to the detector definitions
+##
+## You can ready config/env.sh for more in-depth explanations of the variables
+## and how they can be controlled.
+source config/env.sh
+
+## Setup local environment
+export DATA_PATH=results/dis
+
+## Extra environment variables for DVMP:
+## file tag for these tests
+JUGGLER_FILE_NAME_TAG="dis"
+
+## =============================================================================
+## Step 1: Dummy event generator
+## TODO better file name that encodes the actual configuration we're running
+root -b -q "dis/generator/gen_central_electrons.cxx(${JUGGLER_N_EVENTS}, \".local/${JUGGLER_FILE_NAME_TAG}.hepmc\")"
+if [[ "$?" -ne "0" ]] ; then
+  echo "ERROR running script"
+  exit 1
+fi
+
+## =============================================================================
+## Step 2: finalize
+echo "Moving event generator output into ${DATA_PATH}"
+mv .local/${JUGGLER_FILE_NAME_TAG}.hepmc ${DATA_PATH}/${JUGGLER_FILE_NAME_TAG}.hepmc
+
+## =============================================================================
+## All done!
+echo "dis event generation complete"
diff --git a/dis/scripts/gen_central_electrons.cxx b/dis/generator/gen_central_electrons.cxx
similarity index 100%
rename from dis/scripts/gen_central_electrons.cxx
rename to dis/generator/gen_central_electrons.cxx
diff --git a/dis/generator/placeholder b/dis/generator/placeholder
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dis/util/placeholder b/dis/util/placeholder
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dvcs/config.yml b/dvcs/config.yml
index 73cfc8e89e443ef17df3d92122c0859791726b33..1255c602126617659534258fb03ff646161f25b3 100644
--- a/dvcs/config.yml
+++ b/dvcs/config.yml
@@ -1,8 +1,9 @@
 dvcs:process:
   stage: process
   timeout: 1 hour
+  needs: ["detector"]
   script:
-    - bash dvcs/dvcs.sh
+    - echo "dvcd benchmark"
   artifacts:
     paths:
       - results
diff --git a/dvmp/config.yml b/dvmp/config.yml
index 4a56b84ea109e93b058e9c5e2934e5e3f4f7c6bb..3266b84fd445dae23e90c9e10fd22d4dda003ebe 100644
--- a/dvmp/config.yml
+++ b/dvmp/config.yml
@@ -1,6 +1,6 @@
 dvmp:generate:
   image: eicweb.phy.anl.gov:4567/monte_carlo/lager/lager:unstable
-  stage: generate
+  stage: initialize
   needs: []
   timeout: 1 hours
   cache:
@@ -15,14 +15,14 @@ dvmp:generate:
     paths:
       - results
   script:
-    - ./dvmp/scripts/generate.sh --ebeam 10 --pbeam 100 --config jpsi_central --decay muon --decay electron
+    - ./util/run_many.py ./dvmp/gen.sh --energy 10x100 --config jpsi_central --decay muon --decay electron
 
 dvmp:process:
   stage: process
-  needs: ["dvmp:generate"]
+  needs: ["detector", "dvmp:generate"]
   timeout: 1 hour
   script:
-    - bash dvmp/dvmp.sh
+    - ./util/run_many.py dvmp/dvmp.sh --energy 10x100 --config jpsi_central --decay muon --decay electron --leading jpsi
   artifacts:
     paths:
       - results
diff --git a/dvmp/dvmp.sh b/dvmp/dvmp.sh
old mode 100644
new mode 100755
index 908f94ef814d2461a7dde86bdca4cffb1d0a4ab1..09bdac80669acc550bf7f8dea25413079769eed8
--- a/dvmp/dvmp.sh
+++ b/dvmp/dvmp.sh
@@ -1,24 +1,37 @@
 #!/bin/bash
 
 ## =============================================================================
-## Run the DVMP benchmarks in 5 steps:
-## 1. Build/install detector package
-## 2. Detector simulation through npsim
-## 3. Digitization and reconstruction through Juggler
-## 4. Root-based Physics analyses
-## 5. Finalize
+## Run the DVMP benchmarks in 7 steps:
+## 1. Parse the command line and setup environment
+## 2. Build/install detector package
+## 3. Detector simulation through npsim
+## 4. Digitization and reconstruction through Juggler
+## 5. Root-based Physics analyses
+## 6. Finalize
 ## =============================================================================
 
-echo "Running the DVMP benchmarks"
-
 ## make sure we launch this script from the project root directory
 PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/..
 pushd ${PROJECT_ROOT}
 
+echo "Running the DVMP benchmarks"
+
+
 ## =============================================================================
-## Load the environment variables. To build the detector we need the following
-## variables:
+## Step 1: Setup the environment variables
 ##
+## First parse the command line flags.
+## This sets the following environment variables:
+## - CONFIG:   The specific generator configuration
+## - EBEAM:    The electron beam energy
+## - PBEAM:    The ion beam energy
+## - DECAY:    The decay particle for the generator
+## - LEADING:  Leading particle of interest (J/psi)
+export REQUIRE_DECAY=1
+export REQUIRE_LEADING=1
+source util/parse_cmd.sh $@
+
+## To run the reconstruction, we need the following global variables:
 ## - JUGGLER_INSTALL_PREFIX: Install prefix for Juggler (simu/recon)
 ## - JUGGLER_DETECTOR:       the detector package we want to use for this benchmark
 ## - DETECTOR_PATH:          full path to the detector definitions
@@ -27,23 +40,44 @@ pushd ${PROJECT_ROOT}
 ## and how they can be controlled.
 source config/env.sh
 
-## Extra environment variables for DVMP:
-## file tag for these tests
-JUGGLER_FILE_NAME_TAG="dvmp"
-# Generator file, hardcoded for now FIXME
-JUGGLER_GEN_FILE="results/dvmp/jpsi_central_electron-10on100-gen.hepmc"
-# FIXME use the input file name, as we will be generating a lot of these
-# in the future...
-## note: these variables need to be exported to be accessible from
-##       the juggler options.py. We should really work on a dedicated
-##       juggler launcher to get rid of these "magic" variables. FIXME
-export JUGGLER_SIM_FILE="sim_${JUGGLER_FILE_NAME_TAG}.root"
-export JUGGLER_REC_FILE="rec_${JUGGLER_FILE_NAME_TAG}.root"
+## We also need the following benchmark-specific variables:
+##
+## - BENCHMARK_TAG: Unique identified for this benchmark process.
+## - DATA_PATH:     Place to store our persistent output artifacts.
+##
+## You can read dvmp/env.sh for more in-depth explanations of the variables.
+source dvmp/env.sh
 
+## Get a unique file names based on the configuration options
+GEN_FILE=${DATA_PATH}/`util/print_fname.sh \
+                  --ebeam $EBEAM \
+                  --pbeam $PBEAM \
+                  --decay $DECAY \
+                  --config $CONFIG \
+                  --type gen`.hepmc
+SIM_FILE=${LOCAL_PREFIX}/`util/print_fname.sh \
+                  --ebeam $EBEAM \
+                  --pbeam $PBEAM \
+                  --decay $DECAY \
+                  --config $CONFIG \
+                  --type sim`.root
+REC_FILE=${LOCAL_PREFIX}/`util/print_fname.sh \
+                  --ebeam $EBEAM \
+                  --pbeam $PBEAM \
+                  --decay $DECAY \
+                  --config $CONFIG \
+                  --type rec`.root
+PLOT_PREFIX=${DATA_PATH}/`util/print_fname.sh \
+                  --ebeam $EBEAM \
+                  --pbeam $PBEAM \
+                  --decay $DECAY \
+                  --config $CONFIG \
+                  --type rec`
 
 ## =============================================================================
 ## Step 1: Build/install the desired detector package
-bash util/build_detector.sh
+# moved to different CI step TODO remove
+#bash util/build_detector.sh
 
 ## =============================================================================
 ## Step 2: Run the simulation
@@ -53,8 +87,8 @@ npsim --runType batch \
       -v WARNING \
       --numberOfEvents ${JUGGLER_N_EVENTS} \
       --compactFile ${DETECTOR_PATH}/${JUGGLER_DETECTOR}.xml \
-      --inputFiles ${JUGGLER_GEN_FILE} \
-      --outputFile ${JUGGLER_SIM_FILE}
+      --inputFiles ${GEN_FILE} \
+      --outputFile ${SIM_FILE}
 if [ "$?" -ne "0" ] ; then
   echo "ERROR running npsim"
   exit 1
@@ -63,7 +97,17 @@ fi
 ## =============================================================================
 ## Step 3: Run digitization & reconstruction
 echo "Running the digitization and reconstruction"
-# FIXME Need to figure out how to pass file name to juggler from the commandline
+## FIXME Need to figure out how to pass file name to juggler from the commandline
+## the tracker_reconstruction.py options file uses the following environment
+## variables:
+## - JUGGLER_SIM_FILE:    input detector simulation
+## - JUGGLER_REC_FILE:    output reconstructed data
+## - JUGGLER_DETECTOR_PATH: Location of the detector geometry
+## - JUGGLER_N_EVENTS:    number of events to process (part of global environment)
+## - JUGGLER_DETECTOR:    detector package (part of global environment)
+export JUGGLER_SIM_FILE=${SIM_FILE}
+export JUGGLER_REC_FILE=${REC_FILE}
+export JUGGLER_DETECTOR_PATH=${DETECTOR_PATH}
 xenv -x ${JUGGLER_INSTALL_PREFIX}/Juggler.xenv \
   gaudirun.py options/tracker_reconstruction.py
 if [ "$?" -ne "0" ] ; then
@@ -75,11 +119,12 @@ ls -l
 ## =============================================================================
 ## Step 4: Analysis
 root -b -q "dvmp/analysis/vm_mass.cxx(\
- \"${JUGGLER_REC_FILE}\", \
- \"jpsi\", \
- \"electron\", \
+ \"${REC_FILE}\", \
+ \"${LEADING}\", \
+ \"${DECAY}\", \
  \"${JUGGLER_DETECTOR}\", \
- \"results/dvmp/plot\")"
+ \"${PLOT_PREFIX}\")"
+
 
 if [ "$?" -ne "0" ] ; then
   echo "ERROR running root script"
@@ -88,17 +133,17 @@ fi
 
 ## =============================================================================
 ## Step 5: finalize
-echo "Finalizing ${JUGGLER_FILE_NAME_TAG} benchmark"
+echo "Finalizing DVMP benchmark"
 
 ## Copy over reconsturction artifacts as long as we don't have
 ## too many events
 if [ "${JUGGLER_N_EVENTS}" -lt "500" ] ; then 
-  cp ${JUGGLER_REC_FILE} results/dvmp/.
+  cp ${REC_FILE} ${DATA_PATH}
 fi
 
 ## cleanup output files
-rm ${JUGGLER_REC_FILE} ${JUGGLER_SIM_FILE}
+rm ${REC_FILE} ${SIM_FILE}
 
 ## =============================================================================
 ## All done!
-echo "${JUGGLER_FILE_NAME_TAG} benchmarks complete"
+echo "DVMP benchmarks complete"
diff --git a/dvmp/env.sh b/dvmp/env.sh
new file mode 100644
index 0000000000000000000000000000000000000000..db5500d43e8d1ac00a2488cadfd01e14a7041039
--- /dev/null
+++ b/dvmp/env.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+## =============================================================================
+## Local configuration variables for this particular benchmark 
+## It defines the following additional variables: 
+##
+##  - BENCHMARK_TAG:          Tag to identify this particular benchmark
+##  - DATA_PATH:              Data path for all artifact output
+##
+## =============================================================================
+
+## Tag for the local benchmark. Should be the same as the directory name for
+## this particular benchmark set (for clarity). 
+## This tag is used for the output artifacts directory (results/${JUGGLER_TAG}) 
+## and a tag in some of the output files.
+export BENCHMARK_TAG="dvmp"
+echo "Setting up the local environment for the ${BENCHMARK_TAG^^} benchmarks"
+
+## Data path for all artifact output
+export DATA_PATH="results/${BENCHMARK_TAG}"
+mkdir -p ${DATA_PATH}
+echo "DATA_PATH:              ${DATA_PATH}"
+
+## =============================================================================
+## That's all!
+echo "Local environment setup complete."
diff --git a/dvmp/gen.sh b/dvmp/gen.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c1998e7ec16903f8578839b7cf978c246e79a0ba
--- /dev/null
+++ b/dvmp/gen.sh
@@ -0,0 +1,110 @@
+#!/bin/bash
+
+## =============================================================================
+## Run a single instance of the DVMP generator (lAger)
+## Runs in 5 steps:
+##   1. Parse the command line and setup the environment
+##   2. Check if we can load the requested file from the cache
+##   3. Create our configuration fil
+##   4. Run the actual generator
+##   5. Finalize
+## =============================================================================
+
+## make sure we launch this script from the project root directory
+PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/..
+pushd ${PROJECT_ROOT}
+
+## =============================================================================
+## Step 1: Setup the environment variables
+##
+## First parse the command line flags.
+## This sets the following environment variables:
+## - CONFIG:   The specific generator configuration
+## - EBEAM:    The electron beam energy
+## - PBEAM:    The ion beam energy
+## - DECAY:    The decay particle for the generator
+export REQUIRE_DECAY=1
+source util/parse_cmd.sh $@
+
+## To run the generator, we need the following global variables:
+##
+## - LOCAL_PREFIX:      Place to cache local packages and data
+## - JUGGLER_N_EVENTS:  Number of events to process
+## - JUGGLER_RNG_SEED:  Random seed for event generation.
+##
+## You can read config/env.sh for more in-depth explanations of the variables
+## and how they can be controlled.
+source config/env.sh
+
+## We also need the following benchmark-specific variables:
+##
+## - BENCHMARK_TAG: Unique identified for this benchmark process.
+## - DATA_PATH:     Place to store our persistent output artifacts.
+##
+## You can read dvmp/env.sh for more in-depth explanations of the variables.
+source dvmp/env.sh
+
+## Get a unique file name based on the configuration options
+FNAME=`util/print_fname.sh \
+                  --ebeam $EBEAM \
+                  --pbeam $PBEAM \
+                  --decay $DECAY \
+                  --config $CONFIG \
+                  --type gen`
+
+## =============================================================================
+## Step 2: Check if we really need to run, or can use the cache.
+if [ -f "${DATA_PATH}/${FNAME}.hepmc" ]; then
+  echo "Found cached generator output for $FNAME, no need to rerun"
+  exit 
+fi
+
+echo "Generator output for $FNAME not found in cache, need to run generator"
+
+## =============================================================================
+## Step 3: Create generator configuration file
+
+## process decay info
+BRANCHING=
+DECAY_PID=
+if [ $DECAY = "electron" ]; then
+  BRANCHING="0.05971"
+  DECAY_PID="11"
+elif [ $DECAY = "muon" ]; then
+  BRANCHING="0.05961"
+  DECAY_PID="13"
+fi
+
+## generate the config file for this generator setup
+CONFIG_IN="${BENCHMARK_TAG}/generator/${CONFIG}.json.in"
+echo "Creating generator configuration file ${FNAME}.json"
+if [ ! -f ${CONFIG_IN} ]; then
+  echo "ERROR: cannot find master config file ${CONFIG_IN}"
+  exit 1
+fi
+sed "s/@TAG@/${FNAME}/" $CONFIG_IN | \
+  sed "s/@EBEAM@/${EBEAM}/" | \
+  sed "s/@PBEAM@/${PBEAM}/" | \
+  sed "s/@DECAY_LEPTON@/${DECAY_PID}/" | \
+  sed "s/@BRANCHING@/${BRANCHING}/" > .local/${FNAME}.json
+
+## =============================================================================
+## Step 4: Run the event generator
+echo "Running the generator"
+lager -r ${JUGGLER_RNG_SEED} -c .local/${FNAME}.json -e ${JUGGLER_N_EVENTS} -o ${LOCAL_PREFIX}
+if [ "$?" -ne "0" ] ; then
+  echo "ERROR running lAger"
+  exit 1
+fi
+
+## =============================================================================
+## Step 5: Finally, move relevant output into the artifacts directory and clean up
+echo "Moving generator output into ${DATA_PATH}"
+mkdir -p ${DATA_PATH}
+for ext in hepmc json log root ; do
+  mv ${LOCAL_PREFIX}/*.${FNAME}.*.${ext} ${DATA_PATH}/${FNAME}.${ext}
+done
+echo "Cleaning up"
+rm .local/${FNAME}.json
+
+## All done!
diff --git a/dvmp/scripts/generate.sh b/dvmp/scripts/generate.sh
deleted file mode 100755
index 172ed237db03a22ee1a439b92647313b6e9fb1f3..0000000000000000000000000000000000000000
--- a/dvmp/scripts/generate.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/bash
-
-## Init the environment
-source config/env.sh
-
-## Maximum number of generators to run in parallel
-export MT=10
-
-## Generates different configurations from the master configuration
-## for both electron and muon decay channels
-
-echo "Generating DVMP event samples using lAger"
-
-EBEAM=
-PBEAM=
-DECAYS=()
-CONFS=()
-
-while [ $# -gt 0 ]
-do
-  key="$1"
-  case $key in
-    --config)
-      CONFS+=("$2")
-      shift # past argument
-      shift # past value
-      ;;
-    --decay)
-      DECAYS+=("$2")
-      shift # past argument
-      shift # past value
-      ;;
-    --ebeam)
-      EBEAM="$2"
-      shift # past argument
-      shift # past value
-      ;;
-    --pbeam)
-      PBEAM="$2"
-      shift # past argument
-      shift # past value
-      ;;
-    *)    # unknown option
-      echo "unknown option"
-      exit 1
-      ;;
-  esac
-done
-
-if [ ${#CONFS[@]} -eq 0 ]; then
-  echo "ERROR: need one or more config names: --config <config name> "
-  exit 1
-elif [ ${#DECAYS[@]} -eq 0 ]; then
-  echo "ERROR: need one or more decay types: --decay muon/electron"
-  exit 1
-elif [ -z $EBEAM ]; then
-  echo "ERROR: EBEAM not defined: --EBEAM <energy>"
-  exit 1
-elif [ -z $PBEAM ]; then
-  echo "ERROR: PBEAM not defined: --PBEAM <energy>"
-  exit 1
-fi
-
-## loop over all our configurations and run the generator in parallel
-
-parallel -j ${MT} \
-   "dvmp/scripts/run_generator_instance.sh --ebeam ${EBEAM} --pbeam ${PBEAM} --config {1} --decay {2}" \
-  ::: "${CONFS[@]}" ::: "${DECAYS[@]}"
-
-CONFIG_BASE=`basename ${CONFIG} .json.in`
-
-echo "Event generation finished"
diff --git a/dvmp/scripts/print_fname.sh b/dvmp/scripts/print_fname.sh
deleted file mode 100755
index 7648678315b1072ee62bb0acb50aa0be15b4ad99..0000000000000000000000000000000000000000
--- a/dvmp/scripts/print_fname.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-
-## Simple script to output a unified file name based on a set of data options
-
-EBEAM=
-PBEAM=
-DECAY=
-CONFIG=
-TYPE=
-
-while [ $# -gt 0 ]; do
-  key=$1
-  case $key in
-    --ebeam)
-      EBEAM="$2"
-      shift
-      shift
-      ;;
-    --pbeam)
-      PBEAM="$2"
-      shift
-      shift
-      ;;
-    --decay)
-      DECAY="$2"
-      shift
-      shift
-      ;;
-    --config)
-      CONFIG="$2"
-      shift
-      shift
-      ;;
-    --type)
-      TYPE="$2"
-      shift
-      shift
-      ;;
-    *)
-      echo "Unknown option $key to print_fname, aborting..."
-      exit 1
-  esac
-done
-
-if [ -z $EBEAM ]; then
-  echo "EBEAM not defined in print_fname, aborting..."
-  exit 1
-elif [ -z $PBEAM ]; then
-  echo "PBEAM not defined in print_fname, aborting..."
-  exit 1
-elif [ -z $DECAY ]; then
-  echo "DECAY not defined in print_fname, aborting..."
-  exit 1
-elif [ -z $CONFIG ]; then
-  echo "CONFIG not defined in print_fname, aborting..."
-elif [ -z $TYPE ]; then
-  echo "TYPE not defined in print_fname, aborting..."
-fi
-
-echo "${CONFIG}_${DECAY}-${EBEAM}on${PBEAM}-${TYPE}"
diff --git a/dvmp/scripts/run_generator_instance.sh b/dvmp/scripts/run_generator_instance.sh
deleted file mode 100755
index 2564299bc96f739a3255026d5ac22b653b389698..0000000000000000000000000000000000000000
--- a/dvmp/scripts/run_generator_instance.sh
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/bin/bash
-
-## Init the environment
-source config/env.sh
-
-## Generator configuration
-## We use generator-level n-events, which needs to be larger or equal to 
-## the number of juggler events
-export NEVENTS=1000
-if [ ${JUGGLER_N_EVENTS} \> ${NEVENTS} ]; then
-  NEVENTS=${JUGGLER_N_EVENTS}
-fi
-
-## Our random seed
-export RNG_SEED=1
-
-## Setup local environment
-export DATA_PATH=results/dvmp
-
-
-EBEAM=
-PBEAM=
-DECAY=
-CONFIG=
-
-while [ $# -gt 0 ]; do
-  key=$1
-  case $key in
-    --ebeam)
-      EBEAM="$2"
-      shift
-      shift
-      ;;
-    --pbeam)
-      PBEAM="$2"
-      shift
-      shift
-      ;;
-    --decay)
-      DECAY="$2"
-      shift
-      shift
-      ;;
-    --config)
-      CONFIG="$2"
-      shift
-      shift
-      ;;
-    *)
-      echo "Unknown option $key to run_generator(), aborting..."
-      exit 1
-  esac
-done
-
-if [ -z $EBEAM ]; then
-  echo "EBEAM not defined in run_generator, aborting..."
-  exit 1
-elif [ -z $PBEAM ]; then
-  echo "PBEAM not defined in run_generator, aborting..."
-  exit 1
-elif [ -z $DECAY ]; then
-  echo "DECAY not defined in run_generator, aborting..."
-  exit 1
-elif [ $DECAY != "electron" ] && [ $DECAY != "muon" ] ; then
-  echo "Unknown decay channel $DECAY, aborting..."
-  exit 1
-elif [ -z $CONFIG ]; then
-  echo "CONFIG not defined in run_generator, aborting..."
-fi
-
-pushd dvmp
-FNAME=`scripts/print_fname.sh \
-                  --ebeam $EBEAM \
-                  --pbeam $PBEAM \
-                  --decay $DECAY \
-                  --config $CONFIG \
-                  --type gen`
-if [ -f "${DATA_PATH}/${FNAME}.hepmc" ]; then
-  echo "Found cached generator output for $FNAME, no need to rerun"
-  exit 
-fi
-
-echo "Generator output for $FNAME not found in cache, need to run generator"
-
-## process decay info
-BRANCHING=
-DECAY_PID=
-if [ $DECAY = "electron" ]; then
-  BRANCHING="0.05971"
-  DECAY_PID="11"
-elif [ $DECAY = "muon" ]; then
-  BRANCHING="0.05961"
-  DECAY_PID="13"
-fi
-
-## generate the config file for this generator setup
-CONFIG_IN="generator/${CONFIG}.json.in"
-echo "Creating generator configuration file ${FNAME}.json"
-if [ ! -f ${CONFIG_IN} ]; then
-  echo "ERROR: cannot find master config file ${CONFIG_IN}"
-  exit 1
-fi
-sed "s/@TAG@/${FNAME}/" $CONFIG_IN | \
-  sed "s/@EBEAM@/${EBEAM}/" | \
-  sed "s/@PBEAM@/${PBEAM}/" | \
-  sed "s/@DECAY_LEPTON@/${DECAY_PID}/" | \
-  sed "s/@BRANCHING@/${BRANCHING}/" > ${FNAME}.json
-
-## New we can run the generator
-echo "Running the generator"
-lager -r ${RNG_SEED} -c ${FNAME}.json -e ${NEVENTS} -o .
-
-ls -lrth 
-popd
-
-
-## Finally, move relevant output into the artifacts directory
-echo "Moving generator output into ${DATA_PATH}"
-mkdir -p ${DATA_PATH}
-for ext in hepmc json log root ; do
-  mv dvmp/*.${FNAME}.*.${ext} ${DATA_PATH}/${FNAME}.${ext}
-done
diff --git a/options/tracker_reconstruction.py b/options/tracker_reconstruction.py
index a9181a0a6beeeb464a341165bce4d1a8b16d8909..a3bc67cb9249b8656d75c0fe1921ad3b82f30dea 100644
--- a/options/tracker_reconstruction.py
+++ b/options/tracker_reconstruction.py
@@ -12,7 +12,7 @@ if "JUGGLER_DETECTOR" in os.environ :
 input_sim_file  = str(os.environ["JUGGLER_SIM_FILE"])
 output_rec_file = str(os.environ["JUGGLER_REC_FILE"])
 n_events = str(os.environ["JUGGLER_N_EVENTS"])
-detector_path = str(os.environ["DETECTOR_PATH"])
+detector_path = str(os.environ["JUGGLER_DETECTOR_PATH"])
 
 geo_service  = GeoSvc("GeoSvc",
         detectors=["{}/{}.xml".format(detector_path, detector_name)])
diff --git a/util/build_detector.sh b/util/build_detector.sh
index 066b11c2f1257286c0c282b59fb272866fc79d5d..03641f48151b95011700f80ffd1c0814417b47aa 100755
--- a/util/build_detector.sh
+++ b/util/build_detector.sh
@@ -18,7 +18,7 @@ pushd ${PROJECT_ROOT}
 ## - DETECTOR_PATH:    full path for the detector definitions
 ##                     this is the same as ${DETECTOR_PREFIX}/${JUGGLER_DETECTOR}
 ##
-## You can ready config/env.sh for more in-depth explanations of the variables
+## You can read config/env.sh for more in-depth explanations of the variables
 ## and how they can be controlled.
 source config/env.sh
 
diff --git a/util/parse_cmd.sh b/util/parse_cmd.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9bf2f55319c4cf13d8dd73165580e148e94186dd
--- /dev/null
+++ b/util/parse_cmd.sh
@@ -0,0 +1,125 @@
+#!/bin/bash
+
+## =============================================================================
+## Generic utility script to parse command line arguments for the various
+## bash scripts that control the CI. This script should be source'd with
+## command line arguments from a bash-like (non-POSIX) shell such as
+## bash or zsh.
+##
+## To control some of the functionality of the script, you can set the following
+## environment variables prior to calling the script:
+##   - REQUIRE_DECAY:     require the --decay flag to be set
+## =============================================================================
+
+## make sure we launch this script from the project root directory
+PROJECT_ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"/..
+pushd ${PROJECT_ROOT}
+
+## =============================================================================
+## Step 1: Process the command line arguments
+
+function print_the_help {
+  echo "USAGE:    --ebeam E --pbeam E --config C1 --decay D2"
+  echo "          [--config C2 --decay D2 --decay D3 ...]"
+  echo "REQUIRED ARGUMENTS:"
+  echo "          --ebeam       Electron beam energy"
+  echo "          --pbeam       Ion beam energy"
+  echo "          --config      Generator configuration identifiers (at least one)"
+  if [ ! -z ${REQUIRE_DECAY} ]; then
+    echo "        --decay       Specific decay particle (e.g. muon)."
+  fi
+  if [ ! -z ${REQUIRE_LEADING} ]; then
+    echo "        --leading     Leading particle of interest (e.g. jpsi)."
+  fi
+  echo "          -h,--help     Print this message"
+  echo ""
+  echo "  Generate multiple monte carlo samples for a desired process." 
+  exit
+}
+
+## Required variables
+EBEAM=
+PBEAM=
+DECAYS=
+CONFIG=
+
+while [ $# -gt 0 ]
+do
+  key="$1"
+  case $key in
+    --config)
+      CONFIG="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    --ebeam)
+      EBEAM="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    --pbeam)
+      PBEAM="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    --leading)
+      LEADING="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    --decay)
+      DECAY="$2"
+      shift # past argument
+      shift # past value
+      ;;
+    -h|--help)
+      print_the_help
+      exit 0
+      ;;
+    *)    # unknown option
+      echo "unknown option"
+      exit 1
+      ;;
+  esac
+done
+
+if [ -z $CONFIG ]; then
+  echo "ERROR: CONFIG not defined: --config <config>"
+  print_the_help
+  exit 1
+elif [ -z $EBEAM ]; then
+  echo "ERROR: EBEAM not defined: --ebeam <energy>"
+  print_the_help
+  exit 1
+elif [ -z $PBEAM ]; then
+  echo "ERROR: PBEAM not defined: --pbeam <energy>"
+  print_the_help
+  exit 1
+elif [ -z $LEADING ] && [ ! -z $REQUIRE_LEADING ]; then
+  echo "ERROR: LEADING not defined: --leading <channel>"
+  print_the_help
+  exit 1
+elif [ ! -z $LEADING ] && [ -z $REQUIRE_LEADING ]; then
+  echo "ERROR: LEADING flag specified but not required"
+  print_the_help
+  exit 1
+elif [ -z $DECAY ] && [ ! -z $REQUIRE_DECAY ]; then
+  echo "ERROR: DECAY not defined: --decay <channel>"
+  print_the_help
+  exit 1
+elif [ ! -z $DECAY ] && [ -z $REQUIRE_DECAY ]; then
+  echo "ERROR: DECAY flag specified but not required"
+  print_the_help
+  exit 1
+fi
+
+## Export the configured variables
+export CONFIG
+export EBEAM
+export PBEAM
+if [ ! -z $REQUIRE_LEADING ]; then
+  export LEADING
+fi
+if [ ! -z $REQUIRE_DECAY ]; then
+  export DECAY
+fi
diff --git a/util/print_fname.sh b/util/print_fname.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7c7bcce72bb48c7f4bce47a3bec470bc9149248e
--- /dev/null
+++ b/util/print_fname.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+
+## =============================================================================
+## Simple script to output a unified file name based on a set of data options
+## Note: this file name will not have an extension, as it is mean to be used as
+##       a file name root.
+
+function print_the_help {
+  echo "USAGE:    print_fname [arguments]"
+  echo "REQUIRED ARGUMENTS:"
+  echo "          --ebeam       Electron beam energy"
+  echo "          --pbeam       Ion beam energy"
+  echo "          --config      Generator configuration identifier"
+  echo "          --type        What type of output file is this? (e.g. sim, rec, ...)"
+  echo "OPTIONAL ARGUMENTS:"
+  echo "          --decay       Specific decay particle (if applicable)."
+  echo "          -h,--help     Print this message"
+  echo ""
+  echo "  This script will generate a unique file name for the benchmark output."
+  exit
+}
+
+## =============================================================================
+## Process the command line arguments
+
+## Required variables
+EBEAM=
+PBEAM=
+CONFIG=
+TYPE=
+
+## Optional variables
+DECAY=
+
+while [ $# -gt 0 ]; do
+  key=$1
+  case $key in
+    --ebeam)
+      EBEAM="$2"
+      shift
+      shift
+      ;;
+    --pbeam)
+      PBEAM="$2"
+      shift
+      shift
+      ;;
+    --config)
+      CONFIG="$2"
+      shift
+      shift
+      ;;
+    --type)
+      TYPE="$2"
+      shift
+      shift
+      ;;
+    --decay)
+      DECAY="$2"
+      shift
+      shift
+      ;;
+    -h|--help)
+      print_the_help
+      exit 0
+      ;;
+    *)
+      echo "Unknown option $key to print_fname, aborting..."
+      exit 1
+  esac
+done
+
+if [ -z $EBEAM ]; then
+  echo "EBEAM not defined in print_fname, aborting..."
+  print_the_help
+  exit 1
+elif [ -z $PBEAM ]; then
+  echo "PBEAM not defined in print_fname, aborting..."
+  print_the_help
+  exit 1
+elif [ -z $CONFIG ]; then
+  echo "CONFIG not defined in print_fname, aborting..."
+  print_the_help
+  exit 1
+elif [ -z $TYPE ]; then
+  echo "TYPE not defined in print_fname, aborting..."
+  print_the_help
+  exit 1
+fi
+
+
+## =============================================================================
+## Generate a unique identifier based on the configuration arguments
+
+## Add decay info to CONFIG if requested
+if [ ! -z $DECAY ]; then
+  CONFIG=${CONFIG}_${DECAY}
+fi
+
+echo "${TYPE}-${CONFIG}-${EBEAM}on${PBEAM}"
+
+## all done.
diff --git a/util/run_many.py b/util/run_many.py
new file mode 100755
index 0000000000000000000000000000000000000000..13796e4a7d39b75267a2f6adbad7454d8ca4f50d
--- /dev/null
+++ b/util/run_many.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+
+""" 
+This script will run a CI generator or processing script for multiple configurations.
+
+Author: Sylvester Joosten <sjoosten@anl.gov>
+"""
+
+import os
+import argparse
+from multiprocessing import Pool, get_context
+from tempfile import NamedTemporaryFile
+
+class InvalidArgumentError(Exception):
+    pass
+
+parser = argparse.ArgumentParser()
+parser.add_argument(
+        'command',
+        help="Script to be launched in parallel")
+parser.add_argument(
+        '--energy',
+        dest='energies',
+        action='append',
+        help='One or more beam energy pairs (e.g. 10x100)',
+        required=True)
+parser.add_argument(
+        '--config',
+        dest='configs',
+        action='append',
+        help='One or more configurations',
+        required=True)
+parser.add_argument(
+        '--leading',
+        dest='leads',
+        action='append',
+        help='One or more leading particles(opt.)',
+        required=False)
+parser.add_argument(
+        '--decay',
+        dest='decays',
+        action='append',
+        help='One or more decay channels (opt.)',
+        required=False)
+parser.add_argument(
+        '--nproc',
+        dest='nproc',
+        default=5,
+        type=int,
+        help='Number of processes to launch in parallel',
+        required=False)
+
+def worker(command):
+    '''Execute the command in a system call, with the supplied argument string.'''
+    ## use a temporary file to capture the terminal output, and then
+    ## print the terminal output once the command finishes
+    with NamedTemporaryFile() as f:
+        cmd = [command, '2>1 >', f.name]
+        cmd = ' '.join(cmd)
+        print("Executing '{}'".format(cmd))
+        os.system(cmd)
+        with open(f.name) as log:
+            print(log.read())
+
+if __name__ == '__main__':
+    args = parser.parse_args()
+    print('Launching CI script in parallel for multiple settings')
+    for e in args.energies:
+        beam_setting = e.split('x')
+        if not beam_setting[0].isnumeric() or not beam_setting[1].isnumeric():
+            print("Error: invalid beam energy setting:", e)
+            raise InvalidArgumentError
+
+    if not os.path.exists(args.command):
+        print("Error: Script not found:", args.command)
+        raise InvalidArgumentError
+
+    if args.nproc < 1 or args.nproc > 50:
+        print("Error: Invalid process limit (should be 1-50):", args.nproc)
+        raise InvalidArgumentError
+
+    print(' - command: {}'.format(args.command))
+    print(' - energies: {}'.format(args.energies))
+    print(' - config: {}'.format(args.configs))
+    print(' - nproc: {}'.format(args.nproc))
+    if (args.leads):
+        print(' - leading: {}'.format(args.leads))
+    if (args.decays):
+        print(' - decay: {}'.format(args.decays))
+
+    ## Expand our command and argument list for all combinatorics
+    cmds = []
+    decays = args.decays if args.decays else [None]
+    leads = args.leads if args.leads else [None]
+    for e in args.energies:
+        for c in args.configs:
+            for l in leads:
+                for d in decays:
+                    beam_setting = e.split('x')
+                    cmd = [args.command,
+                           '--ebeam', beam_setting[0],
+                           '--pbeam', beam_setting[1],
+                           '--config', c]
+                    if l is not None:
+                        cmd += ['--leading', l]
+                    if d is not None:
+                        cmd += ['--decay', d]
+                    cmds.append(' '.join(cmd))
+
+    ## create a process pool
+    ## note that I'm using themultiprocessing.get_context function to setup
+    ## a context where subprocesses are created using the new "spawn" process
+    ## which avoids deadlocks that sometimes happen in the default dispatch
+    with get_context('spawn').Pool(processes=args.nproc) as pool:
+        pool.map(worker, cmds)
+
+    ## That's all!