Commit fb0730d9 authored by Jens Korinth's avatar Jens Korinth

Implement global 'maxThreads' parameter

* better control to restrict parallelism (~ memory consumption)
* global parameter --maxThreads [NUM] controls general.maxThreads in Vivado
* applies to both synthesis and implementation
* removed superfluous implicit in Composer
parent a8f64503
......@@ -42,11 +42,10 @@ trait Composer {
* @param archFeatures ArchitectureFeatures (optional).
* @param platformFeatures Platform features (optional).
* @param cfg implicit Configuration instance
* @param maxThreads maximum number of parallel threads to use (default: unlimited)
* @return Composer.Result with error code / additional data
**/
def compose(bd: Composition, target: Target, f: Double = 0, archFeatures: Seq[Feature] = Seq(),
platformFeatures: Seq[Feature] = Seq())(implicit cfg: Configuration, maxThreads: Option[Int] = None): Result
platformFeatures: Seq[Feature] = Seq())(implicit cfg: Configuration): Result
/** Removes all intermediate files for the run, leaving results.
* @param bd Composition to synthesize
......@@ -75,8 +74,8 @@ object Composer {
}
}
def apply(i: Implementation)(implicit cfg: Configuration, maxThreads: Option[Int]): Composer = i match {
case Implementation.Vivado => new VivadoComposer()(cfg, maxThreads)
def apply(i: Implementation)(implicit cfg: Configuration): Composer = i match {
case Implementation.Vivado => new VivadoComposer()(cfg)
}
/** Make a name for the Composer project. */
......
......@@ -37,7 +37,7 @@ import ComposeResult._
import LogFormatter._
/** Implementation of [[Composer]] for Vivado Design Suite. */
class VivadoComposer()(implicit cfg: Configuration, maxThreads: Option[Int]) extends Composer {
class VivadoComposer()(implicit cfg: Configuration) extends Composer {
import VivadoComposer._
private[this] val logger = de.tu_darmstadt.cs.esa.tapasco.Logging.logger(this.getClass)
......@@ -46,8 +46,8 @@ class VivadoComposer()(implicit cfg: Configuration, maxThreads: Option[Int]) ext
/** @inheritdoc */
def compose(bd: Composition, target: Target, f: Heuristics.Frequency = 0, archFeatures: Seq[Feature] = Seq(),
platformFeatures: Seq[Feature] = Seq()) (implicit cfg: Configuration, maxThreads: Option[Int]): Composer.Result = {
logger.debug("VivadoComposer uses at most {} threads", maxThreads getOrElse "unlimited")
platformFeatures: Seq[Feature] = Seq()) (implicit cfg: Configuration): Composer.Result = {
logger.debug("VivadoComposer uses at most {} threads", cfg.maxThreads getOrElse "unlimited")
// create output struct
val files = VivadoComposer.Files(bd, target, f, archFeatures ++ platformFeatures)
// create output directory
......@@ -189,8 +189,8 @@ class VivadoComposer()(implicit cfg: Configuration, maxThreads: Option[Int]) ext
(target.pd.hostFrequency map (f => "set tapasco_host_freq %3.0f%s".format(f, NL)) getOrElse "") +
(target.pd.memFrequency map (f => "set tapasco_mem_freq %3.0f%s".format(f, NL)) getOrElse "") +
(target.pd.boardPreset map (bp => "set tapasco_board_preset %s%s".format(bp, NL)) getOrElse "") +
(maxThreads map (mt => "set tapasco_jobs %d%s".format(mt, NL)) getOrElse "") +
(maxThreads map (mt => "set_param general.maxThreads %d%s".format(mt, NL)) getOrElse "") +
(cfg.maxThreads map (mt => "set tapasco_jobs %d%s".format(mt, NL)) getOrElse "") +
(cfg.maxThreads map (mt => "set_param general.maxThreads %d%s".format(mt, NL)) getOrElse "") +
(platformFeatures.map { f => new FeatureTclPrinter("platform").toTcl(f) } mkString NL) +
(archFeatures.map { f => new FeatureTclPrinter("architecture").toTcl(f) } mkString NL) + NL
}
......
......@@ -48,6 +48,8 @@ trait Configuration {
def slurm(enabled: Boolean): Configuration
def parallel: Boolean
def parallel(enabled: Boolean): Configuration
def maxThreads: Option[Int]
def maxThreads(mt: Option[Int]): Configuration
/** Returns the default output directory for the given kernel and target. */
def outputDir(kernel: Kernel, target: Target): Path =
......
......@@ -43,6 +43,7 @@ private case class ConfigurationImpl (
private val _logFile: Option[Path] = None,
slurm: Boolean = false,
parallel: Boolean = false,
maxThreads: Option[Int] = None,
jobs: Seq[Job] = Seq()
) extends Description(descPath: Path) with Configuration {
def descPath(p: Path): Configuration = this.copy(descPath = p)
......@@ -60,6 +61,7 @@ private case class ConfigurationImpl (
def logFile(op: Option[Path]): Configuration = this.copy(_logFile = op)
def slurm(enabled: Boolean): Configuration = this.copy(slurm = enabled)
def parallel(enabled: Boolean): Configuration = this.copy(parallel = enabled)
def maxThreads(mt: Option[Int]): Configuration = this.copy(maxThreads = mt)
def jobs(js: Seq[Job]): Configuration = this.copy(jobs = js)
// these directories must exist
......
......@@ -81,6 +81,7 @@ private object PrettyPrinter {
"PlatformDir = " + c.platformDir,
"Slurm = " + c.slurm,
"Parallel = " + c.parallel,
"MaxThreads = " + (c.maxThreads getOrElse "unlimited"),
"Jobs = " + c.jobs
) mkString NL
......
......@@ -346,6 +346,7 @@ package object json {
(JsPath \ "LogFile").readNullable[Path] ~
(JsPath \ "Slurm").readNullable[Boolean].map (_ getOrElse false) ~
(JsPath \ "Parallel").readNullable[Boolean].map (_ getOrElse false) ~
(JsPath \ "MaxThreads").readNullable[Int] ~
(JsPath \ "Jobs").read[Seq[Job]]
) (ConfigurationImpl.apply _)
implicit private val configurationWrites: Writes[ConfigurationImpl] = (
......@@ -358,6 +359,7 @@ package object json {
(JsPath \ "LogFile").writeNullable[Path] ~
(JsPath \ "Slurm").write[Boolean] ~
(JsPath \ "Parallel").write[Boolean] ~
(JsPath \ "MaxThreads").writeNullable[Int] ~
(JsPath \ "Jobs").write[Seq[Job]]
) (unlift(ConfigurationImpl.unapply _))
implicit object ConfigurationWrites extends Writes[Configuration] {
......
......@@ -47,6 +47,10 @@ object CommandLineParser extends JavaTokenParsers {
p => ("Parallel", p._2 getOrElse true)
}
private[parser] def maxThreads: Parser[(String, Int)] = param("maxthreads", false) ~ wholeNumber ^^ {
p => ("MaxThreads", p._2.toInt)
}
private[parser] def configFile: Parser[String] = param("configfile", false) ~> path
private[parser] def jobsFile: Parser[String] = param("jobsfile", false) ~> path
......
......@@ -25,6 +25,7 @@ private object ConfigurationParser {
entityDir ^^ { p => (p._1.toString, p._2) } |
slurm ^^ { p => (p._1, p._2.toString) } |
parallel ^^ { p => (p._1, p._2.toString) } |
maxThreads ^^ { p => (p._1, p._2.toString) } |
jobsFile ^^ { p => ("JobsFile", p) }
)
......@@ -50,12 +51,15 @@ private object ConfigurationParser {
m.get("Platforms") foreach { d => c = c.platformDir(Paths.get(d)) }
m.get("Slurm") foreach { d => c = c.slurm(d.toBoolean) }
m.get("Parallel") foreach { d => c = c.parallel(d.toBoolean) }
m.get("MaxThreads") foreach { d => c = c.maxThreads(Some(d.toInt)) }
m.get("LogFile") foreach { d => c = c.logFile(Some(Paths.get(d))) }
if (jobs.nonEmpty || m.get("JobsFile").nonEmpty) {
val ret = if (jobs.nonEmpty || m.get("JobsFile").nonEmpty) {
c.jobs(m.get("JobsFile") map (p => readJobsFile(p)) getOrElse jobs)
} else {
c
}
logger.debug("configuration: {}", ret)
ret
}
/* Configuration @} */
}
......
......@@ -17,6 +17,8 @@ object Usage {
--jobsFile [FILE] Path to Json file with Jobs array
--slurm Activate SLURM cluster execution (requires sbatch)
--parallel Execute all jobs in parallel (careful!)
--maxThreads [NUM] Limit internal parallelism of activities (e.g., Vivado)
to the given number of threads.
Bulk Import Job: bulkimport [options*]
--csv [FILE] [FILE] should be in comma-separated values (CSV) format
......
......@@ -24,7 +24,7 @@ class ComposeTask(composition: Composition,
logFile: Option[String] = None,
debugMode: Option[String] = None,
val onComplete: Boolean => Unit)
(implicit cfg: Configuration, maxThreads: Option[Int] = None) extends Task with LogTracking {
(implicit cfg: Configuration) extends Task with LogTracking {
private[this] implicit val _logger = de.tu_darmstadt.cs.esa.tapasco.Logging.logger(getClass)
private[this] val _slurm = Slurm.enabled
private[this] var _composerResult: Option[Composer.Result] = None
......@@ -41,7 +41,7 @@ class ComposeTask(composition: Composition,
private def nodeExecution: Boolean = {
val appender = LogFileTracker.setupLogFileAppender(_logFile.toString)
val composer = Composer(implementation)(cfg, maxThreads)
val composer = Composer(implementation)(cfg)
_logger.debug("launching compose run for {}@{} [current thread: {}], logfile {}",
target.ad.name: Object, target.pd.name: Object, Thread.currentThread.getName(): Object, _logFile: Object)
if (debugMode.isEmpty) {
......
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