Commit d26a3ff8 authored by Jaime Arias's avatar Jaime Arias
Browse files

fix oar generation script

parent 4d74498e
......@@ -30,6 +30,7 @@ __pycache__/
# slurm batch
slurm
oar
# editor
.vscode
......@@ -41,4 +42,3 @@ slurm-*.out
# git rm -r .ipynb_checkpoints/
# End of https://www.gitignore.io/api/jupyternotebooks
......@@ -3,9 +3,10 @@
import os
import stat
import sys
from itertools import product
from functools import reduce
from collections import ChainMap
from functools import reduce
from itertools import product
from time import time
sbatch_header = """\
#!/bin/bash
......@@ -24,7 +25,7 @@ module load gcc/8.3.0/openmpi/3.1.4
oar_header = """\
#!/bin/bash
#
#OAR --name {experiment_name}_{model_instance}_n{nodes}-th{threads}
#OAR --name {experiment_name}
#OAR --resource /nodes={nodes}/cpu=1/core={threads},walltime={timeout}
#OAR --stderr {error_file}
#OAR --stdout {output_file}
......@@ -75,8 +76,7 @@ def generate_model_instance_path(model_name, model_instance, extension, paths):
return model_path
def generate_formula_path(identifier, extension, model_name, model_instance,
paths):
def generate_formula_path(identifier, extension, model_name, model_instance, paths):
"""Generates the absolute path of a formula
Parameters
......@@ -98,13 +98,11 @@ def generate_formula_path(identifier, extension, model_name, model_instance,
Formula path
"""
name = f"{model_instance}-{identifier}.{extension}"
formula_path = os.path.join(paths["formulas"], model_name, model_instance,
name)
formula_path = os.path.join(paths["formulas"], model_name, model_instance, name)
return formula_path
def pmcsog_run(parameters, threads, model_name, model_instance, formula,
paths):
def pmcsog_run(parameters, threads, model_name, model_instance, formula, paths):
"""Generates the string with the command to execute pmc-sog
Parameters
......@@ -127,21 +125,20 @@ def pmcsog_run(parameters, threads, model_name, model_instance, formula,
str
Command to execute pmc-sog
"""
formula = generate_formula_path(formula, 'ltl.reduced', model_name,
model_instance, paths)
model = generate_model_instance_path(model_name, model_instance, 'net',
paths)
tool = os.path.join(paths['tools'], 'pmc-sog')
parallelisation = parameters['parallelisation']
formula = generate_formula_path(
formula, "ltl.reduced", model_name, model_instance, paths
)
model = generate_model_instance_path(model_name, model_instance, "net", paths)
tool = os.path.join(paths["tools"], "pmc-sog")
parallelisation = parameters["parallelisation"]
algorithm = parameters['strategy'].strip()
algorithm = '"{}"'.format(algorithm) if algorithm != "default" else ''
algorithm = parameters["strategy"].strip()
algorithm = '"{}"'.format(algorithm) if algorithm != "default" else ""
return f"{tool} {parallelisation} {threads} {model} {formula} {algorithm}"
def ltsmin_run(parameters, threads, model_name, model_instance, formula,
paths):
def ltsmin_run(parameters, threads, model_name, model_instance, formula, paths):
"""Generates the string with the command to execute pnml2lts-mc
Parameters
......@@ -164,11 +161,9 @@ def ltsmin_run(parameters, threads, model_name, model_instance, formula,
str
Command to execute pnml2lts-mc
"""
tool = os.path.join(paths['tools'], 'pnml2lts-mc')
formula = generate_formula_path(formula, 'ltl', model_name, model_instance,
paths)
model = generate_model_instance_path(model_name, model_instance, 'pnml',
paths)
tool = os.path.join(paths["tools"], "pnml2lts-mc")
formula = generate_formula_path(formula, "ltl", model_name, model_instance, paths)
model = generate_model_instance_path(model_name, model_instance, "pnml", paths)
strategy = parameters["strategy"]
size = parameters["size"]
......@@ -176,8 +171,7 @@ def ltsmin_run(parameters, threads, model_name, model_instance, formula,
return f"{tool} --strategy={strategy} --size={size} --threads={threads} --ltl={formula} {model}"
def tool_command(tool_dict, threads, model_name, model_instance, formula,
paths):
def tool_command(tool_dict, threads, model_name, model_instance, formula, paths):
"""Factory method that returns the correct command depending on the tool
Parameters
......@@ -200,16 +194,18 @@ def tool_command(tool_dict, threads, model_name, model_instance, formula,
str
Command of the tool
"""
tool_name = tool_dict['name']
tool_parameters = tool_dict['parameters']
tool_name = tool_dict["name"]
tool_parameters = tool_dict["parameters"]
command = ""
if (tool_name == "pmc-sog"):
command = pmcsog_run(tool_parameters, threads, model_name,
model_instance, formula, paths)
elif (tool_name == "pnml2lts-mc"):
command = ltsmin_run(tool_parameters, threads, model_name,
model_instance, formula, paths)
if tool_name == "pmc-sog":
command = pmcsog_run(
tool_parameters, threads, model_name, model_instance, formula, paths
)
elif tool_name == "pnml2lts-mc":
command = ltsmin_run(
tool_parameters, threads, model_name, model_instance, formula, paths
)
else:
sys.exit("{} is not handled yet".format(tool_name))
......@@ -242,24 +238,43 @@ def srun(command, nodes, threads, timeout, job_name, output_folder):
return f"srun -n {nodes} --resv-ports --cpus-per-task={threads} --time={timeout} --output={output_file} --error={error_file} --job-name={job_name} {command}"
def mpi_run(command, nodes, threads, timeout_minutes, job_name, output_folder):
error_file = f"{output_folder}/{job_name}.err"
output_file = f"{output_folder}/{job_name}.out"
timeout = timeout_minutes * 60
return f"mpirun -machinefile $OAR_NODEFILE --npernode {nodes} -cpus-per-proc {threads} --timeout {timeout} {command} > {output_file} 2>{error_file}"
def generate_experiment_name(tool_dict):
"""Generate the name of the experiment"""
tool_name = tool_dict["name"]
tool_params_dict = tool_dict["parameters"]
tool_parameters = tool_dict["parameters"][
"parallelisation"] + "_" if tool_name == "pmc-sog" else ''
tool_parameters = (
tool_dict["parameters"]["parallelisation"] + "_"
if tool_name == "pmc-sog"
else ""
)
tool_parameters += tool_params_dict["strategy"]
tool_parameters = reduce(
(lambda s, v: s.replace(*v)),
[['(poprem)', '-default'], ['(poprem shy)', '-shy'], ['Cou', 'couv']],
tool_parameters)
[["(poprem)", "-default"], ["(poprem shy)", "-shy"], ["Cou", "couv"]],
tool_parameters,
)
return f"{tool_name}_{tool_parameters}"
def generate_oar(tool_dict, nodes, threads, model_dict, formulas_ids,
timeout, paths):
def generate_oar(
tool_dict,
nodes,
threads,
model_dict,
formulas_ids,
timeout,
paths,
oar_timeout="2:00:00",
):
"""Generates a slurm batch of a experiment to be executed on the cluster
Parameters
......@@ -280,45 +295,56 @@ def generate_oar(tool_dict, nodes, threads, model_dict, formulas_ids,
Dictionary with the paths of the project
"""
tool_name = tool_dict["name"]
model_name = model_dict['name']
model_instances = model_dict['instances']
model_name = model_dict["name"]
model_instances = model_dict["instances"]
experiment_name = generate_experiment_name(tool_dict)
# folder where oar scripts will be saved
oar_folder = os.path.join(paths['oar'], 'experiments', tool_name, experiment_name, model_name)
oar_folder = os.path.join(
paths["oar"], "experiments", tool_name, experiment_name, model_name
)
create_folder(oar_folder)
# print srun command for each model_instance
for model_instance in model_instances:
oar_name = f"{model_instance}-n{nodes}-th{threads}.oar"
oar_file = os.path.join(oar_folder, oar_name)
oar_job = f"{experiment_name}_{model_instance}_n{nodes}-th{threads}"
oar_file = os.path.join(oar_folder, f"{oar_job}.oar")
# folder where the outputs will be saved
output_folder = os.path.join(paths['results'], tool_name,
experiment_name, model_name,
model_instance)
output_folder = os.path.join(
paths["results"], tool_name, experiment_name, model_name, model_instance
)
create_folder(output_folder)
error_file = f"{output_folder}/{experiment_name}.err"
output_file = f"{output_folder}/{experiment_name}.out"
error_file = f"{output_folder}/{oar_job}.err"
output_file = f"{output_folder}/{oar_job}.out"
header = oar_header.format(experiment_name=experiment_name,
model_instance=model_instance,
nodes=nodes,
threads=threads,
timeout="2:00:00",
error_file=error_file,
output_file=output_file)
header = oar_header.format(
experiment_name=oar_job,
model_instance=model_instance,
nodes=nodes,
threads=threads,
timeout=oar_timeout,
error_file=error_file,
output_file=output_file,
)
with open(oar_file, 'w') as f:
with open(oar_file, "w") as f:
f.write(header)
for formula in formulas_ids:
command = tool_command(tool_dict, threads, model_name,
model_instance, formula, paths)
command = tool_command(
tool_dict, threads, model_name, model_instance, formula, paths
)
job_name = f"{oar_job}-f{formula}"
f.write(command)
mpi_command = mpi_run(
command, nodes, threads, timeout, job_name, output_folder
)
f.write(mpi_command)
f.write("\n\n")
# give oar script the exec right
......@@ -326,8 +352,9 @@ def generate_oar(tool_dict, nodes, threads, model_dict, formulas_ids,
os.chmod(oar_file, st.st_mode | stat.S_IEXEC)
def generate_sbatch(tool_dict, nodes, threads, model_dict, formulas_ids,
timeout, paths):
def generate_sbatch(
tool_dict, nodes, threads, model_dict, formulas_ids, timeout, paths
):
"""Generates a slurm batch of a experiment to be executed on the cluster
Parameters
......@@ -348,40 +375,47 @@ def generate_sbatch(tool_dict, nodes, threads, model_dict, formulas_ids,
Dictionary with the paths of the project
"""
tool_name = tool_dict["name"]
model_name = model_dict['name']
model_instances = model_dict['instances']
model_name = model_dict["name"]
model_instances = model_dict["instances"]
experiment_name = generate_experiment_name(tool_dict)
header = sbatch_header.format(experiment_name=experiment_name,
model_name=model_name,
nodes=nodes,
threads=threads)
header = sbatch_header.format(
experiment_name=experiment_name,
model_name=model_name,
nodes=nodes,
threads=threads,
)
sbatch_folder = os.path.join(paths['slurm'], 'experiments', tool_name,
experiment_name, model_name)
sbatch_folder = os.path.join(
paths["slurm"], "experiments", tool_name, experiment_name, model_name
)
create_folder(sbatch_folder)
sbatch_name = f"n{nodes}-th{threads}.sbatch"
sbatch_file = os.path.join(sbatch_folder, sbatch_name)
with open(sbatch_file, 'w') as sbatch_file:
with open(sbatch_file, "w") as sbatch_file:
sbatch_file.write(header)
# print srun command for each model_instance
for model_instance in model_instances:
output_folder = os.path.join(paths['results'], tool_name,
experiment_name, model_name,
model_instance)
output_folder = os.path.join(
paths["results"], tool_name, experiment_name, model_name, model_instance
)
create_folder(output_folder)
for formula in formulas_ids:
command = tool_command(tool_dict, threads, model_name,
model_instance, formula, paths)
command = tool_command(
tool_dict, threads, model_name, model_instance, formula, paths
)
job_name = f"{tool_name}_{model_instance}-n{nodes}-th{threads}-f{formula}"
job_name = (
f"{tool_name}_{model_instance}-n{nodes}-th{threads}-f{formula}"
)
srun_command = srun(command, nodes, threads, timeout, job_name,
output_folder)
srun_command = srun(
command, nodes, threads, timeout, job_name, output_folder
)
sbatch_file.write(srun_command)
sbatch_file.write("\n\n")
......@@ -390,23 +424,24 @@ def generate_sbatch(tool_dict, nodes, threads, model_dict, formulas_ids,
def create_default_paths():
"""Create the default path for the project"""
base_folder = os.path.abspath(
os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir)
)
paths = {
# Absolute path where are stored the formulas, models, and scripts
'project': base_folder,
"project": base_folder,
# Folder where the formulas are saved
'formulas': os.path.join(base_folder, "formulas"),
"formulas": os.path.join(base_folder, "formulas"),
# Folder where the models are saved
'models': os.path.join(base_folder, "models"),
"models": os.path.join(base_folder, "models"),
# Folder where the results will be saved
'results': os.path.join(base_folder, "results"),
"results": os.path.join(base_folder, "results"),
# Folder where the slurm batches will be saved
'slurm': os.path.join(base_folder, "slurm"),
"slurm": os.path.join(base_folder, "slurm"),
# Folder where the oar batches will be saved
'oar': os.path.join(base_folder, "oar"),
"oar": os.path.join(base_folder, "oar"),
# Folder where the tool are saved
'tools': os.path.join(base_folder, "tools")
"tools": os.path.join(base_folder, "tools"),
}
# Create paths if they don't exist
......@@ -418,21 +453,23 @@ def create_default_paths():
def explode_tool(tool):
"""Generates a tool dictionary for each parameter"""
parameters = [[{
name: value
} for value in values] for name, values in tool["parameters"].items()]
parameters = [
[{name: value} for value in values]
for name, values in tool["parameters"].items()
]
parameters = product(*parameters)
result = [{
"name": tool["name"],
"parameters": dict(ChainMap(*parameter))
} for parameter in parameters]
result = [
{"name": tool["name"], "parameters": dict(ChainMap(*parameter))}
for parameter in parameters
]
return result
def generate_multiple_batchs(tools, models, formulas, nodes_list,
threads_list, timeout, paths, launcher):
def generate_multiple_batchs(
tools, models, formulas, nodes_list, threads_list, timeout, paths, launcher
):
"""Generates the slurm batch for several experiments
Parameters
......@@ -462,22 +499,24 @@ def generate_multiple_batchs(tools, models, formulas, nodes_list,
for nodes in nodes_list:
for threads in threads_list:
if launcher == "slurm":
generate_sbatch(tool, nodes, threads, model, formulas,
timeout, paths)
generate_sbatch(
tool, nodes, threads, model, formulas, timeout, paths
)
elif launcher == "oar":
generate_oar(tool, nodes, threads, model, formulas,
timeout, paths)
generate_oar(
tool, nodes, threads, model, formulas, timeout, paths
)
else:
print(f"{launcher} is not supported")
sys.exit(0)
if __name__ == '__main__':
if __name__ == "__main__":
# Default paths
paths = create_default_paths()
# slurm or oar
launcher="oar"
launcher = "oar"
# Timeout: 20 minutes
timeout = 20
......@@ -493,38 +532,46 @@ if __name__ == '__main__':
formulas = [n for n in range(1, nb_formulas + 1)]
# Models to be run
models = [{
# "name": "philo",
# "instances": ["philo5", "philo10", "philo20"]
# }, {
# "name": "train",
# "instances": ["train12", "train24", "train48", "train96"]
# }, {
"name": "tring",
"instances": [ "tring10" ] # "tring5", "tring20"
# }, {
# "name":
# "robot",
# "instances": ["robot20"] #"robot20", "robot50", "robot2", "robot5", "robot10"]
# }, {
# "name": "spool",
# "instances": ["spool4", "spool5"] #, "spool1", "spool2", "spool3"]
}]
models = [
{
# "name": "philo",
# "instances": ["philo5", "philo10", "philo20"]
# }, {
# "name": "train",
# "instances": ["train12", "train24", "train48", "train96"]
# }, {
"name": "tring",
"instances": ["tring10"] # "tring5", "tring20"
# }, {
# "name":
# "robot",
# "instances": ["robot20"] #"robot20", "robot50", "robot2", "robot5", "robot10"]
# }, {
# "name": "spool",
# "instances": ["spool4", "spool5"] #, "spool1", "spool2", "spool3"]
}
]
# Tools to be compared
tools = [{
"name": "pmc-sog",
"parameters": {
"parallelisation": ["otfPOR", "otfPRPOR"], # 'otf', 'otfPR', 'otfP', 'otfC',
"strategy": ['Cou99(poprem)', 'Cou99(poprem shy)'] #, 'default']
tools = [
{
"name": "pmc-sog",
"parameters": {
"parallelisation": [
"otfPOR",
"otfPRPOR",
], # 'otf', 'otfPR', 'otfP', 'otfC',
"strategy": ["Cou99(poprem)", "Cou99(poprem shy)"], # , 'default']
}
# }, {
# "name": "pnml2lts-mc",
# "parameters": {
# "size": ["90%"],
# "strategy": ['dfs', 'ndfs']
# }
}
# }, {
# "name": "pnml2lts-mc",
# "parameters": {
# "size": ["90%"],
# "strategy": ['dfs', 'ndfs']
# }
}]
generate_multiple_batchs(tools, models, formulas, nodes, threads, timeout,
paths, launcher)
]
generate_multiple_batchs(
tools, models, formulas, nodes, threads, timeout, paths, launcher
)
Markdown is supported
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