forked from M-Labs/artiq
scheduler: support priorities
This commit is contained in:
parent
2f910921f5
commit
d6ced1c780
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue