-
-
Notifications
You must be signed in to change notification settings - Fork 150
Template job scripts with Jinja #370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e10cede
41bdccb
29ce63e
8f94ba8
00702ed
6386c3e
4cd56d2
9f4d995
9e571ee
7fb6f75
918d173
1edb3cd
caad975
272565a
88f1bad
5939574
97d64ce
29aa9bb
ca8b697
2fe7e30
32e1d3f
def8d48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,52 +57,32 @@ def __init__( | |
| use_stdin = dask.config.get("jobqueue.%s.use-stdin" % self.config_name) | ||
| self.use_stdin = use_stdin | ||
|
|
||
| header_lines = [] | ||
| # LSF header build | ||
| if self.name is not None: | ||
| header_lines.append("#BSUB -J %s" % self.job_name) | ||
| if self.log_directory is not None: | ||
| header_lines.append( | ||
| "#BSUB -e %s/%s-%%J.err" % (self.log_directory, self.name or "worker") | ||
| ) | ||
| header_lines.append( | ||
| "#BSUB -o %s/%s-%%J.out" % (self.log_directory, self.name or "worker") | ||
| ) | ||
| if queue is not None: | ||
| header_lines.append("#BSUB -q %s" % queue) | ||
| if project is not None: | ||
| header_lines.append('#BSUB -P "%s"' % project) | ||
| if ncpus is None: | ||
| # Compute default cores specifications | ||
| ncpus = self.worker_cores | ||
| logger.info( | ||
| "ncpus specification for LSF not set, initializing it to %s" % ncpus | ||
| ) | ||
| if ncpus is not None: | ||
| header_lines.append("#BSUB -n %s" % ncpus) | ||
| if ncpus > 1: | ||
| # span[hosts=1] _might_ affect queue waiting | ||
| # time, and is not required if ncpus==1 | ||
| header_lines.append('#BSUB -R "span[hosts=1]"') | ||
| if mem is None: | ||
| # Compute default memory specifications | ||
| mem = self.worker_memory | ||
| logger.info( | ||
| "mem specification for LSF not set, initializing it to %s bytes" % mem | ||
| ) | ||
| if mem is not None: | ||
| lsf_units = lsf_units if lsf_units is not None else lsf_detect_units() | ||
| memory_string = lsf_format_bytes_ceil(mem, lsf_units=lsf_units) | ||
| header_lines.append("#BSUB -M %s" % memory_string) | ||
| if walltime is not None: | ||
| header_lines.append("#BSUB -W %s" % walltime) | ||
| header_lines.extend(["#BSUB %s" % arg for arg in job_extra]) | ||
|
|
||
| # Declare class attribute that shall be overridden | ||
| self.job_header = "\n".join(header_lines) | ||
| self.job_header = self.template_env.get_template("lsf_job_header.j2").render( | ||
| name=self.name, | ||
| job_name=self.job_name, | ||
| log_directory=self.log_directory, | ||
| queue=queue, | ||
| project=project, | ||
| ncpus=ncpus, | ||
| worker_cores=self.worker_cores, | ||
| mem=mem, | ||
| worker_memory=self.worker_memory, | ||
| lsf_units=lsf_units, | ||
| walltime=walltime, | ||
| job_extra=job_extra, | ||
| logger=logger, | ||
| ) | ||
|
|
||
| logger.debug("Job script: \n %s" % self.job_script()) | ||
|
|
||
| @property | ||
| def template_env(self): | ||
| env = super().template_env | ||
| env.filters["set_ncpus"] = set_ncpus | ||
| env.filters["set_mem"] = set_mem | ||
| env.filters["format_memory"] = format_memory | ||
| return env | ||
|
|
||
| async def _submit_job(self, script_filename): | ||
| if self.use_stdin: | ||
| piped_cmd = [self.submit_command + "< " + script_filename + " 2> /dev/null"] | ||
|
|
@@ -112,6 +92,29 @@ async def _submit_job(self, script_filename): | |
| return result | ||
|
|
||
|
|
||
| def set_ncpus(ncpus, worker_cores, logger): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for LSF, couldn't we code this in the template file?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's possible though the templating logic can easily get messy and it is often easier and cleaner to offload more complicated logic to filters (which is exactly what is done here). Additionally, I don't think you can easily log things from within a Jinja template.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I was thinking of removing the log, which don't seem really useful to me. But actually, in this case, we could have kept the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely agree regarding The |
||
| if ncpus is None: | ||
| ncpus = worker_cores | ||
| logger.info( | ||
| "ncpus specification for LSF not set, initializing it to %s" % ncpus | ||
| ) | ||
| return ncpus | ||
|
|
||
|
|
||
| def set_mem(mem, worker_memory, logger): | ||
| if mem is None: | ||
| mem = worker_memory | ||
| logger.info( | ||
| "mem specification for LSF not set, initializing it to %s bytes" % mem | ||
| ) | ||
| return mem | ||
|
|
||
|
|
||
| def format_memory(mem, lsf_units): | ||
| lsf_units = lsf_units if lsf_units is not None else lsf_detect_units() | ||
| return lsf_format_bytes_ceil(mem, lsf_units=lsf_units) | ||
|
|
||
|
|
||
| def lsf_format_bytes_ceil(n, lsf_units="mb"): | ||
| """Format bytes as text | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't this be done directly in the template file?