diff --git a/expe.py b/expe.py index f87dece..fff9945 100644 --- a/expe.py +++ b/expe.py @@ -1,36 +1,87 @@ -import subprocess +import os +import random import itertools +import subprocess + +class Run: + def __init__(self, cmd_tpl): + self.cmd_tpl = cmd_tpl + + def single(self, doe): + for params in doe: + cmd = self.cmd_tpl.format(**params) + subprocess.run(cmd, shell=True) -def batchsplit(axe, njobs): - for i in range(0,len(axe),njobs): - yield axe[i:i+njobs] - - -def batchrun(key, jobs, params, cmd_tpl): - procs = [] - for job in jobs: - params[key] = job - cmd = cmd_tpl.format(**params) + def all(self, doe): + queue = [] + for params in doe: + cmd = self.cmd_tpl.format(**params) p = subprocess.Popen(cmd, shell=True) - procs.append(p) + queue.append(p) - for job in procs: - job.wait() + for p in queue: + p.wait() -def expe(axes): - for p in itertools.product(*[axes[k] for k in axes]): - params = {} - for i in range(len(axes)): - params[list(axes.keys())[i]] = p[i] - yield params + def batch(self, doe, batch_size = None): + if batch_size is None: + batch_size = os.cpu_count() + + nb = 0 + queue = [] + for params in doe: + if nb >= batch_size: + for p in queue: + p.wait() + queue.clear() + nb = 0 + else: + cmd = self.cmd_tpl.format(**params) + p = subprocess.Popen(cmd, shell=True) + queue.append(p) + nb += 1 + # in case batch_size = float("inf") + for p in queue: + p.wait() + + + def qsub(self, doe): + for params in doe: + cmd = self.cmd_tpl.format(**params) + print("TODO qsub",cmd) + + +class Expe: + def __init__(self, **kwargs): + self.names = [] + self.axes = [] + self.static_params = kwargs + + def __iter__(self): + for p in itertools.product( *(self.axes) ): + params = self.static_params + for i in range(len(self.names)): + params[self.names[i]] = p[i] + yield params + + def forall(self, name, iters): + self.names.append(name) + self.axes.append(iters) + return self + + def random(self, name, nb, rmin=0, rmax=1): + """Note: this intentionally produce the SAME random sequence for each product of axes.""" + self.names.append(name) + def rand(): + for i in range(nb): + yield random.random() * (rmax-rmin) + rmin + self.axes.append(rand()) + return self if __name__ == "__main__": - import os - import subprocess const_args=" --nb-sensors 5 --sensor-range 0.2 --domain-width 50 --iters 10000" solvers = ["num_greedy","bit_greedy","num_rand","bit_rand"] @@ -40,10 +91,16 @@ if __name__ == "__main__": if not os.path.exists(outdir): os.mkdir(outdir) - cmd_tpl = "python3 snp.py --no-plot --dir {outdir} --seed {{seed}} --solver {{solver}}".format(outdir=outdir) - for seed in range(nbruns): - for params in expe({"seed":[seed]}): - for by_four in batchsplit(solvers, 4): - batchrun("solver", by_four, params, cmd_tpl) + cmd = "echo \"--no-plot --dir {outdir} --seed {seed} --solver {solver}\"" + # for seed in range(nbruns): + # for params in expe({"seed":[seed]}): + # for by_four in batchsplit(solvers, 4): + # batchrun("solver", by_four, params, cmd_tpl) + doe = Expe(outdir=outdir).forall("seed",range(nbruns)).forall("solver",solvers) + + Run(cmd).single(doe) + Run(cmd).all(doe) + Run(cmd).batch(doe) + Run(cmd).qsub(doe)