scheduler: support priorities

This commit is contained in:
Sebastien Bourdeauducq 2015-05-24 01:09:22 +08:00
parent 2f910921f5
commit d6ced1c780
3 changed files with 28 additions and 20 deletions

View File

@ -32,12 +32,14 @@ def get_argparser():
subparsers.required = True subparsers.required = True
parser_add = subparsers.add_parser("submit", help="submit an experiment") parser_add = subparsers.add_parser("submit", help="submit an experiment")
parser_add.add_argument( parser_add.add_argument("-t", "--timed", default=None, type=str,
"-t", "--timed", default=None, type=str,
help="set a due date for the experiment") help="set a due date for the experiment")
parser_add.add_argument("-p", "--pipeline", default="main", type=str, parser_add.add_argument("-p", "--pipeline", default="main", type=str,
help="pipeline to run the experiment in " help="pipeline to run the experiment in "
"(default: %(default)s)") "(default: %(default)s)")
parser_add.add_argument("-P", "--priority", default=0, type=int,
help="priority (higher value means sooner "
"scheduling, default: %(default)s)")
parser_add.add_argument("-e", "--experiment", default=None, parser_add.add_argument("-e", "--experiment", default=None,
help="experiment to run") help="experiment to run")
parser_add.add_argument("file", parser_add.add_argument("file",
@ -104,7 +106,7 @@ def _action_submit(remote, args):
due_date = None due_date = None
else: else:
due_date = time.mktime(parse_date(args.timed).timetuple()) due_date = time.mktime(parse_date(args.timed).timetuple())
rid = remote.submit(args.pipeline, expid, due_date) rid = remote.submit(args.pipeline, expid, args.priority, due_date)
print("RID: {}".format(rid)) print("RID: {}".format(rid))
@ -132,11 +134,13 @@ def _show_schedule(schedule):
clear_screen() clear_screen()
if schedule: if schedule:
l = sorted(schedule.items(), l = sorted(schedule.items(),
key=lambda x: (x[1]["due_date"] or 0, x[0])) key=lambda x: (x[1]["due_date"] or 0,
table = PrettyTable(["RID", "Pipeline", " Status ", "Due date", -x[1]["priority"],
"File", "Experiment", "Arguments"]) x[0]))
table = PrettyTable(["RID", "Pipeline", " Status ", "Prio",
"Due date", "File", "Experiment", "Arguments"])
for rid, v in l: for rid, v in l:
row = [rid, v["pipeline"], v["status"]] row = [rid, v["pipeline"], v["status"], v["priority"]]
if v["due_date"] is None: if v["due_date"] is None:
row.append("") row.append("")
else: else:

View File

@ -12,13 +12,13 @@ from artiq.tools import format_arguments
class _ScheduleModel(DictSyncModel): class _ScheduleModel(DictSyncModel):
def __init__(self, parent, init): def __init__(self, parent, init):
DictSyncModel.__init__(self, DictSyncModel.__init__(self,
["RID", "Pipeline", "Status", "Due date", ["RID", "Pipeline", "Status", "Prio", "Due date",
"File", "Experiment", "Arguments"], "File", "Experiment", "Arguments"],
parent, init) parent, init)
def sort_key(self, k, v): def sort_key(self, k, v):
# order by due date, and then by RID # order by due date, and then by priority and RID
return (v["due_date"] or 0, k) return (v["due_date"] or 0, -v["priority"], k)
def convert(self, k, v, column): def convert(self, k, v, column):
if column == 0: if column == 0:
@ -28,19 +28,21 @@ class _ScheduleModel(DictSyncModel):
elif column == 2: elif column == 2:
return v["status"] return v["status"]
elif column == 3: elif column == 3:
return str(v["priority"])
elif column == 4:
if v["due_date"] is None: if v["due_date"] is None:
return "" return ""
else: else:
return time.strftime("%m/%d %H:%M:%S", return time.strftime("%m/%d %H:%M:%S",
time.localtime(v["due_date"])) time.localtime(v["due_date"]))
elif column == 4:
return v["expid"]["file"]
elif column == 5: elif column == 5:
return v["expid"]["file"]
elif column == 6:
if v["expid"]["experiment"] is None: if v["expid"]["experiment"] is None:
return "" return ""
else: else:
return v["expid"]["experiment"] return v["expid"]["experiment"]
elif column == 6: elif column == 7:
return format_arguments(v["expid"]["arguments"]) return format_arguments(v["expid"]["arguments"])
else: else:
raise ValueError raise ValueError

View File

@ -45,12 +45,13 @@ def _mk_worker_method(name):
class Run: class Run:
def __init__(self, rid, pipeline_name, def __init__(self, rid, pipeline_name,
expid, due_date, expid, priority, due_date,
worker_handlers, notifier): worker_handlers, notifier):
# called through pool # called through pool
self.rid = rid self.rid = rid
self.pipeline_name = pipeline_name self.pipeline_name = pipeline_name
self.expid = expid self.expid = expid
self.priority = priority
self.due_date = due_date self.due_date = due_date
self._status = RunStatus.pending self._status = RunStatus.pending
@ -61,6 +62,7 @@ class Run:
self._notifier[self.rid] = { self._notifier[self.rid] = {
"pipeline": self.pipeline_name, "pipeline": self.pipeline_name,
"expid": self.expid, "expid": self.expid,
"priority": self.priority,
"due_date": self.due_date, "due_date": self.due_date,
"status": self._status.name "status": self._status.name
} }
@ -83,7 +85,7 @@ class Run:
else: else:
overdue = int(now > self.due_date) overdue = int(now > self.due_date)
due_date_k = -self.due_date due_date_k = -self.due_date
return (overdue, due_date_k, -self.rid) return (overdue, self.priority, due_date_k, -self.rid)
@asyncio.coroutine @asyncio.coroutine
def close(self): def close(self):
@ -123,10 +125,10 @@ class RunPool:
self._worker_handlers = worker_handlers self._worker_handlers = worker_handlers
self._notifier = notifier self._notifier = notifier
def submit(self, expid, due_date, pipeline_name): def submit(self, expid, priority, due_date, pipeline_name):
# called through scheduler # called through scheduler
rid = self._ridc.get() rid = self._ridc.get()
run = Run(rid, pipeline_name, expid, due_date, run = Run(rid, pipeline_name, expid, priority, due_date,
self._worker_handlers, self._notifier) self._worker_handlers, self._notifier)
self.runs[rid] = run self.runs[rid] = run
if self.submitted_callback is not None: if self.submitted_callback is not None:
@ -349,7 +351,7 @@ class Scheduler:
if self._pipelines: if self._pipelines:
logger.warning("some pipelines were not garbage-collected") logger.warning("some pipelines were not garbage-collected")
def submit(self, pipeline_name, expid, due_date): def submit(self, pipeline_name, expid, priority, due_date):
if self._terminated: if self._terminated:
return return
try: try:
@ -360,7 +362,7 @@ class Scheduler:
self._worker_handlers, self.notifier) self._worker_handlers, self.notifier)
self._pipelines[pipeline_name] = pipeline self._pipelines[pipeline_name] = pipeline
pipeline.start() pipeline.start()
return pipeline.pool.submit(expid, due_date, pipeline_name) return pipeline.pool.submit(expid, priority, due_date, pipeline_name)
def delete(self, rid): def delete(self, rid):
self._deleter.delete(rid) self._deleter.delete(rid)