New stage design

This commit is contained in:
Rodrigo Arias 2020-09-02 17:07:09 +02:00
parent d469ccd59d
commit 8110bc2976
12 changed files with 221 additions and 150 deletions

View File

@ -4,28 +4,25 @@
}: }:
{ {
app program
, env ? "" , env ? ""
, argv # bash array as string, example: argv=''(-f "file with spaces" -t 10)'' , argv # bash array as string, example: argv=''(-f "file with spaces" -t 10)''
, program ? "bin/run"
}: }:
stdenv.mkDerivation { stdenv.mkDerivation {
inherit argv; name = "argv";
name = "${app.name}-argv";
preferLocalBuild = true; preferLocalBuild = true;
phases = [ "installPhase" ]; phases = [ "installPhase" ];
installPhase = '' installPhase = ''
mkdir -p $out/bin cat > $out <<EOF
cat > $out/bin/run <<EOF
#!${bash}/bin/bash #!${bash}/bin/bash
# Requires /nix to use bash # Requires /nix to use bash
${env} ${env}
argv=${argv} argv=${argv}
exec ${app}/${program} \''${argv[@]} exec ${program} \''${argv[@]}
EOF EOF
chmod +x $out/bin/run chmod +x $out
''; '';
} }

View File

@ -2,23 +2,23 @@
stdenv stdenv
}: }:
program: {
program
}:
stdenv.mkDerivation { stdenv.mkDerivation {
inherit program; name = "control";
name = "${program.name}-control";
preferLocalBuild = true; preferLocalBuild = true;
phases = [ "installPhase" ]; phases = [ "installPhase" ];
dontPatchShebangs = true; dontPatchShebangs = true;
installPhase = '' installPhase = ''
mkdir -p $out/bin cat > $out <<EOF
cat > $out/bin/run <<EOF
#!/bin/sh #!/bin/sh
#set -e #set -e
for n in {1..30}; do for n in {1..30}; do
$program/bin/run ${program}
done done
EOF EOF
chmod +x $out/bin/run chmod +x $out
''; '';
} }

View File

@ -25,14 +25,17 @@ let
gitBranch = "garlic/seq"; gitBranch = "garlic/seq";
}; };
sbatchWrapper = callPackage ./sbatch.nix { }; runWrappers = {
srunWrapper = callPackage ./srun.nix { }; sbatch = callPackage ./sbatch.nix { };
launchWrapper = callPackage ./launcher.nix { }; srun = callPackage ./srun.nix { };
controlWrapper = callPackage ./control.nix { }; launch = callPackage ./launcher.nix { };
nixsetupWrapper = callPackage ./nix-setup.nix { }; control = callPackage ./control.nix { };
argvWrapper = callPackage ./argv.nix { }; nixsetup= callPackage ./nix-setup.nix { };
statspyWrapper = callPackage ./statspy.nix { }; argv = callPackage ./argv.nix { };
extraeWrapper = callPackage ./extrae.nix { }; statspy = callPackage ./statspy.nix { };
extrae = callPackage ./extrae.nix { };
stagen = callPackage ./stagen.nix { };
};
# Perf is tied to a linux kernel specific version # Perf is tied to a linux kernel specific version
linuxPackages = bsc.linuxPackages_4_4; linuxPackages = bsc.linuxPackages_4_4;

View File

@ -1,114 +1,130 @@
{ {
bsc bsc
, stdenv
, nbody , nbody
, genApp , genApp
, genConfigs , genConfigs
, runWrappers
# Wrappers
, launchWrapper
, sbatchWrapper
, srunWrapper
, argvWrapper
, controlWrapper
, nixsetupWrapper
, statspyWrapper
, extraeWrapper
, perfWrapper
}: }:
with stdenv.lib;
let let
# Set the configuration for the experiment # Set variable configuration for the experiment
config = { varConfig = {
cc = [ bsc.icc ]; cc = [ bsc.icc ];
blocksize = [ 1024 ]; blocksize = [ 1024 ];
}; };
extraConfig = { # Common configuration
common = {
# Compile time nbody config
gitBranch = "garlic/mpi+send"; gitBranch = "garlic/mpi+send";
mpi = bsc.impi; mpi = bsc.impi;
# nbody runtime options
particles = 1024*128; particles = 1024*128;
timesteps = 100; timesteps = 20;
# Resources
ntasksPerNode = "48"; ntasksPerNode = "48";
nodes = "1"; nodes = "1";
time = "02:00:00";
qos = "debug"; # Stage configuration
enableSbatch = true;
enableControl = true;
enableExtrae = false;
enablePerf = false;
# MN4 path
nixPrefix = "/gpfs/projects/bsc15/nix";
}; };
# Compute the cartesian product of all configurations # Compute the cartesian product of all configurations
allConfigs = genConfigs config; configs = map (conf: conf // common) (genConfigs varConfig);
filteredConfigs = with builtins; filter (c: c.blocksize <= 4096) allConfigs;
configs = map (conf: conf // extraConfig) filteredConfigs;
sbatch = conf: app: with conf; sbatchWrapper { stageProgram = stage:
app = app; if stage ? programPath
nixPrefix = "/gpfs/projects/bsc15/nix"; then "${stage}${stage.programPath}" else "${stage}";
w = runWrappers;
sbatch = {stage, conf, ...}: with conf; w.sbatch {
program = stageProgram stage;
exclusive = true; exclusive = true;
inherit ntasksPerNode nodes time qos; time = "02:00:00";
qos = "debug";
jobName = "nbody-bs";
inherit nixPrefix nodes ntasksPerNode;
}; };
srun = app: srunWrapper { control = {stage, conf, ...}: with conf; w.control {
app = app; program = stageProgram stage;
nixPrefix = "/gpfs/projects/bsc15/nix"; };
srun = {stage, conf, ...}: with conf; w.srun {
program = stageProgram stage;
srunOptions = "--cpu-bind=verbose,rank"; srunOptions = "--cpu-bind=verbose,rank";
inherit nixPrefix;
}; };
argv = conf: app: statspy = {stage, conf, ...}: with conf; w.statspy {
with conf; program = stageProgram stage;
argvWrapper { };
app = app;
perf = {stage, conf, ...}: with conf; w.perf {
program = stageProgram stage;
perfArgs = "sched record -a";
};
nixsetup = {stage, conf, ...}: with conf; w.nixsetup {
program = stageProgram stage;
};
extrae = {stage, conf, ...}: w.extrae {
program = stageProgram stage;
traceLib = "mpi"; # mpi -> libtracempi.so
configFile = ./extrae.xml;
};
argv = {stage, conf, ...}: w.argv {
program = stageProgram stage;
env = '' env = ''
set -e set -e
export I_MPI_THREAD_SPLIT=1 export I_MPI_THREAD_SPLIT=1
''; '';
argv = ''(-t ${toString timesteps} -p ${toString particles})''; argv = ''( -t ${toString conf.timesteps}
-p ${toString conf.particles} )'';
}; };
statspy = app: nbodyFn = {stage, conf, ...}: with conf; nbody.override {
statspyWrapper { inherit cc blocksize mpi gitBranch;
app = app;
}; };
extrae = app: stages = with common; []
extraeWrapper { # Use sbatch to request resources first
app = app; ++ optional enableSbatch sbatch
traceLib = "mpi";
configFile = ./extrae.xml;
};
perf = app: # Repeats the next stages N times
perfWrapper { ++ optionals enableControl [ nixsetup control ]
app = app;
perfArgs = "sched record -a";
};
nbodyFn = conf: # Executes srun to launch the program in the requested nodes, and
with conf; # immediately after enters the nix environment again, as slurmstepd launches
nbody.override { inherit cc mpi blocksize gitBranch; }; # the next stages from outside the namespace.
++ [ srun nixsetup ]
pipeline = conf: # Intrumentation with extrae
# sbatch conf ( ++ optional enableExtrae extrae
# nixsetupWrapper (
# controlWrapper (
srun (
nixsetupWrapper (
# extrae (
# perf (
argv conf (
nbodyFn conf
)
# )
# )
)
)
# )
# )
# )
;
# Ideally it should look like this: # Optionally profile the next stages with perf
#pipeline = sbatch nixsetup control argv nbodyFn; ++ optional enablePerf perf
jobs = map pipeline configs; # Execute the nbody app with the argv and env vars
++ [ argv nbodyFn ];
# List of actual programs to be executed
jobs = map (conf: w.stagen { inherit conf stages; }) configs;
in in
launchWrapper jobs # We simply run each program one after another
w.launch jobs

View File

@ -2,29 +2,36 @@
stdenv stdenv
, bash , bash
, extrae , extrae
#, writeShellScriptBin
}: }:
{ {
app program
, traceLib ? "mpi"
, configFile , configFile
, program ? "bin/run" , traceLib
}: }:
#writeShellScriptBin "extraeWrapper" ''
# export EXTRAE_HOME=${extrae}
# export LD_PRELOAD=${extrae}/lib/lib${traceLib}trace.so:$LD_PRELOAD
# export EXTRAE_CONFIG_FILE=${configFile}
# exec ${program}
#''
stdenv.mkDerivation { stdenv.mkDerivation {
name = "${app.name}-extrae"; name = "extrae";
preferLocalBuild = true; preferLocalBuild = true;
phases = [ "installPhase" ]; phases = [ "installPhase" ];
installPhase = '' installPhase = ''
mkdir -p $out/bin cat > $out <<EOF
cat > $out/bin/run <<EOF
#!${bash}/bin/bash #!${bash}/bin/bash
# Requires /nix to use bash
export EXTRAE_HOME=${extrae} export EXTRAE_HOME=${extrae}
export LD_PRELOAD=${extrae}/lib/lib${traceLib}trace.so:$LD_PRELOAD export LD_PRELOAD=${extrae}/lib/lib${traceLib}trace.so:$LD_PRELOAD
export EXTRAE_CONFIG_FILE=${configFile} export EXTRAE_CONFIG_FILE=${configFile}
exec ${app}/${program} exec ${program}
EOF EOF
chmod +x $out/bin/run chmod +x $out
''; '';
} }

View File

@ -12,12 +12,13 @@ with stdenv.lib;
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
name = "nbody"; name = "nbody";
src = /home/Computational/rarias/bsc-nixpkgs/manual/nbody; src = /home/Computational/rarias/bscpkgs/manual/nbody;
#src = builtins.fetchGit { #src = builtins.fetchGit {
# url = "${gitURL}"; # url = "${gitURL}";
# ref = "${gitBranch}"; # ref = "${gitBranch}";
#}; #};
programPath = "/bin/nbody";
buildInputs = [ buildInputs = [
cc cc
@ -38,7 +39,6 @@ stdenv.mkDerivation rec {
installPhase = '' installPhase = ''
mkdir -p $out/bin mkdir -p $out/bin
cp nbody* $out/bin/${name} cp nbody* $out/bin/${name}
ln -s $out/bin/${name} $out/bin/run
''; '';
} }

View File

@ -2,17 +2,17 @@
stdenv stdenv
}: }:
program: {
program
}:
stdenv.mkDerivation { stdenv.mkDerivation {
inherit program; name = "nixsetup";
name = "${program.name}-nixsetup";
preferLocalBuild = true; preferLocalBuild = true;
phases = [ "installPhase" ]; phases = [ "installPhase" ];
dontPatchShebangs = true; dontPatchShebangs = true;
installPhase = '' installPhase = ''
mkdir -p $out/bin cat > $out <<EOF
cat > $out/bin/run <<EOF
#!/bin/sh #!/bin/sh
# We need to enter the nix namespace first, in order to have /nix # We need to enter the nix namespace first, in order to have /nix
@ -21,8 +21,8 @@ stdenv.mkDerivation {
exec nix-setup \$0 exec nix-setup \$0
fi fi
exec $program/bin/run exec ${program}
EOF EOF
chmod +x $out/bin/run chmod +x $out
''; '';
} }

View File

@ -5,22 +5,20 @@
}: }:
{ {
app program
, perfArgs ? "record -a" , perfArgs ? "record -a"
, program ? "bin/run"
}: }:
stdenv.mkDerivation { stdenv.mkDerivation {
name = "${app.name}-perf"; name = "perfWrapper";
preferLocalBuild = true; preferLocalBuild = true;
phases = [ "installPhase" ]; phases = [ "installPhase" ];
installPhase = '' installPhase = ''
mkdir -p $out/bin cat > $out <<EOF
cat > $out/bin/run <<EOF
#!${bash}/bin/bash #!${bash}/bin/bash
exec ${perf}/bin/perf ${perfArgs} ${app}/${program} exec ${perf}/bin/perf ${perfArgs} ${program}
EOF EOF
chmod +x $out/bin/run chmod +x $out
''; '';
} }

View File

@ -4,10 +4,10 @@
}: }:
{ {
app program
, jobName
, chdirPrefix ? "." , chdirPrefix ? "."
, nixPrefix ? "" , nixPrefix ? ""
, argv ? ""
, binary ? "/bin/run" , binary ? "/bin/run"
, ntasks ? null , ntasks ? null
, ntasksPerNode ? null , ntasksPerNode ? null
@ -33,12 +33,9 @@ let
in in
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
name = "${app.name}-job"; name = "sbatch";
preferLocalBuild = true; preferLocalBuild = true;
src = ./.;
buildInputs = [ app ];
phases = [ "installPhase" ]; phases = [ "installPhase" ];
#SBATCH --tasks-per-node=48 #SBATCH --tasks-per-node=48
@ -46,12 +43,13 @@ stdenv.mkDerivation rec {
#SBATCH --cpus-per-task=1 #SBATCH --cpus-per-task=1
dontBuild = true; dontBuild = true;
dontPatchShebangs = true; dontPatchShebangs = true;
programPath = "/${name}";
installPhase = '' installPhase = ''
mkdir -p $out mkdir -p $out
cat > $out/job <<EOF cat > $out/job <<EOF
#!/bin/sh #!/bin/sh
#SBATCH --job-name="${name}" #SBATCH --job-name="${jobName}"
'' ''
+ sbatchOpt "ntasks" ntasks + sbatchOpt "ntasks" ntasks
+ sbatchOpt "ntasks-per-node" ntasksPerNode + sbatchOpt "ntasks-per-node" ntasksPerNode
@ -66,11 +64,10 @@ stdenv.mkDerivation rec {
+ optionalString (extra!=null) extra + optionalString (extra!=null) extra
+ +
'' ''
exec ${nixPrefix}${app}${binary} ${argv} exec ${nixPrefix}${program}
EOF EOF
mkdir -p $out/bin cat > $out/${name} <<EOF
cat > $out/bin/run <<EOF
#!/bin/sh #!/bin/sh
if [ -e "${chdirPrefix}/$(basename $out)" ]; then if [ -e "${chdirPrefix}/$(basename $out)" ]; then
>&2 echo "Execution aborted: '${chdirPrefix}/$(basename $out)' already exists" >&2 echo "Execution aborted: '${chdirPrefix}/$(basename $out)' already exists"
@ -80,6 +77,6 @@ stdenv.mkDerivation rec {
echo sbatch ${nixPrefix}$out/job echo sbatch ${nixPrefix}$out/job
sbatch ${nixPrefix}$out/job sbatch ${nixPrefix}$out/job
EOF EOF
chmod +x $out/bin/run chmod +x $out/${name}
''; '';
} }

View File

@ -2,23 +2,21 @@
stdenv stdenv
}: }:
{ {
app program
, nixPrefix ? "" , nixPrefix ? ""
, srunOptions ? "" , srunOptions ? ""
}: }:
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
name = "${app.name}-srun"; name = "srun";
preferLocalBuild = true; preferLocalBuild = true;
phases = [ "installPhase" ]; phases = [ "installPhase" ];
buildInputs = [ app ];
dontPatchShebangs = true; dontPatchShebangs = true;
installPhase = '' installPhase = ''
mkdir -p $out/bin cat > $out <<EOF
cat > $out/bin/run <<EOF
#!/bin/sh #!/bin/sh
exec srun --mpi=pmi2 ${srunOptions} ${nixPrefix}${app}/bin/run exec srun --mpi=pmi2 ${srunOptions} ${nixPrefix}${program}
EOF EOF
chmod +x $out/bin/run chmod +x $out
''; '';
} }

55
bsc/garlic/stagen.nix Normal file
View File

@ -0,0 +1,55 @@
{
stdenv
, bash
, extrae
, writeShellScriptBin
, jq
}:
{
stages
, conf
, experimentName ? "run"
}:
with stdenv.lib;
let
dStages = foldr (stageFn: {conf, prevStage, stages}: {
conf = conf;
prevStage = stageFn {stage=prevStage; conf=conf;};
stages = [ (stageFn {stage=prevStage; conf=conf;}) ] ++ stages;
})
{conf=conf; stages=[]; prevStage=null;} stages;
stageProgram = stage:
if stage ? programPath
then "${stage}${stage.programPath}" else "${stage}";
linkStages = imap1 (i: s: {
name = "${toString i}-${baseNameOf s.name}";
path = stageProgram s;
}) dStages.stages;
createLinks = builtins.concatStringsSep "\n"
(map (x: "ln -s ${x.path} $out/bin/${x.name}") linkStages);
firstStageLink = (x: x.name) (elemAt linkStages 0);
in
stdenv.mkDerivation {
name = "stagen";
preferLocalBuild = true;
phases = [ "installPhase" ];
buildInputs = [ jq ];
installPhase = ''
mkdir -p $out/bin
${createLinks}
ln -s ${firstStageLink} $out/bin/${experimentName}
cat > $out/config.raw << EOF
${builtins.toJSON conf}
EOF
jq . $out/config.raw > $out/config.json
rm $out/config.raw
'';
}

View File

@ -4,26 +4,26 @@
}: }:
{ {
app program
, outputDir ? "." , outputDir ? "."
, program ? "bin/run"
}: }:
stdenv.mkDerivation { stdenv.mkDerivation {
name = "${app.name}-statspy"; name = "statspy";
preferLocalBuild = true; preferLocalBuild = true;
phases = [ "installPhase" ]; phases = [ "installPhase" ];
programPath = "/bin/${name}";
installPhase = '' installPhase = ''
mkdir -p $out/bin mkdir -p $out/bin
cat > $out/bin/run <<EOF cat > $out/bin/${name} <<EOF
#!${bash}/bin/bash #!${bash}/bin/bash
mkdir -p ${outputDir} mkdir -p ${outputDir}
cat /proc/[0-9]*/stat | sort -n > ${outputDir}/statspy.\$(date +%s.%3N).begin cat /proc/[0-9]*/stat | sort -n > ${outputDir}/statspy.\$(date +%s.%3N).begin
${app}/${program} ${program}
cat /proc/[0-9]*/stat | sort -n > ${outputDir}/statspy.\$(date +%s.%3N).end cat /proc/[0-9]*/stat | sort -n > ${outputDir}/statspy.\$(date +%s.%3N).end
EOF EOF
chmod +x $out/bin/run chmod +x $out/bin/${name}
''; '';
} }