diff --git a/runtime/clap_wrapper.sh b/runtime/clap_wrapper.sh
index f91c35d01..815893bfa 100755
--- a/runtime/clap_wrapper.sh
+++ b/runtime/clap_wrapper.sh
@@ -1,3 +1,3 @@
#!/bin/bash
-LD_PRELOAD=./lib/clap/build/libClap.so $1
+LD_PRELOAD=./lib/clap/build/libClap.so "$1" "$2"
diff --git a/src/main/scala/apps/mm.scala b/src/main/scala/apps/mm.scala
index 282a8e5f6..1813aff81 100644
--- a/src/main/scala/apps/mm.scala
+++ b/src/main/scala/apps/mm.scala
@@ -73,8 +73,8 @@ object mm {
))(zip(p6)(x._1))
)
))(mapSeq(mapSeq(id))(generate(fun(_ => generate(fun(_ => lf32(0.0f)))))) :: (v4`.`v3`.`f32)) |> //
- mapSeq(asScalar o mapSeq(id) o asVector(vw)) |>
- transpose // v3.v4.f
+ mapSeq(asScalar o mapSeq(id) o asVector(vw)) |>
+ transpose // v3.v4.f
)) |> join |> transpose
)) |> join
))
@@ -107,7 +107,8 @@ object mm {
mapWorkGroup(0)(fun(p3 =>
zip(p2)(p3) |> // O'.(v8.v5.f x v8.v7.f)
// FIXME: there seems to be a bug in AdjustArraySizesForAllocations
- oclReduceSeq(AddressSpace.Private)(fun((p13, p14) =>
+// oclReduceSeq(AddressSpace.Private)(fun((p13, p14) =>
+ oclReduceSeq(AddressSpace.Local)(fun((p13, p14) =>
// (v5/^v4).(v7/^v3).v4.v3.f x (v8.v5.f x v8.v7.f)
let (toLocal(makePair(
p14._1 |> join |> split(v6) |> // ((v8 x v5) /^ v6).v6.f
diff --git a/src/main/scala/rise/autotune/configFileGeneration.scala b/src/main/scala/rise/autotune/configFileGeneration.scala
index ac7f0bbca..4143f3afb 100644
--- a/src/main/scala/rise/autotune/configFileGeneration.scala
+++ b/src/main/scala/rise/autotune/configFileGeneration.scala
@@ -1,160 +1,135 @@
package rise.autotune
-import arithexpr.arithmetic.{RangeAdd, RangeMul, Var}
-import rise.core.types.{NatIdentifier}
+import arithexpr.arithmetic.{PosInf, RangeAdd, RangeMul, Var}
+import rise.core.types.{NatIdentifier, TuningParameter}
import scala.collection.mutable.ListBuffer
import constraints._
+import exploration.explorationUtil.jsonParser.readFile
+import play.api.libs.json.Json
object configFileGeneration {
+
def generateJSON(p: Parameters,
c: Set[Constraint],
- tuner: Tuner)
- : String = {
-
- val parametersWDC = distributeConstraints(p, c)
+ tuner: Tuner
+ ): String = {
- assert(check_no_cycle(parametersWDC))
+ val parametersWDCImmutable = distributeConstraints(p, c)
// number of samples for design of experiment phase
val doe = p.size * 10
+ val optimization_iterations = tuner.samples
// create header for hypermapper configuration file
val header =
- s"""{
- | "application_name" : "${tuner.name}",
- | "optimization_objectives" : ["runtime"],
- | "hypermapper_mode" : {
- | "mode" : "client-server"
- | },
- | "feasible_output" : {
- | "enable_feasible_predictor" : true,
- | "name" : "Valid",
- | "true_value" : "True",
- | "false_value" : "False"
- | },
- | "design_of_experiment" : {
- | "doe_type" : "random sampling",
- | "number_of_samples" : ${doe}
- | },
- | "optimization_iterations" : ${tuner.iterations},
- | "input_parameters" : {
- |""".stripMargin
+ s"""{
+ | "application_name" : "${tuner.name}",
+ | "optimization_objectives" : ["runtime"],
+ | "hypermapper_mode" : {
+ | "mode" : "client-server"
+ | },
+ | "log_file" : "${tuner.name}.log",
+ | "feasible_output" : {
+ | "enable_feasible_predictor" : true,
+ | "name" : "Valid",
+ | "true_value" : "True",
+ | "false_value" : "False"
+ | },
+ | "design_of_experiment" : {
+ | "doe_type" : "random sampling",
+ | "number_of_samples" : ${doe}
+ | },
+ | "optimization_iterations" : ${optimization_iterations},
+ | "input_parameters" : {
+ |""".stripMargin
+
// create entry foreach parameter
var parameter = ""
- p.foreach(elem => {
- val parameterRange = elem.range match {
- case RangeAdd(start, stop, step) => {
+ parametersWDCImmutable.foreach{ case (param, wdc) => {
+
+ val (values, constraintsFiltered) = param.range match {
+ case RangeAdd(start, stop, step) => {
// if step is not evaluable use 1 instead
- val stepWidth = step.isEvaluable match{
+ val stepWidth = step.isEvaluable match {
case true => step.eval
case false => 1
}
// avoid filtering of starting 1
- start.eval match {
+ val values = start.eval match {
case 1 => {
stepWidth match {
- case 1 => valuesListToString(
- List.range(start.evalInt, stop.evalInt + 1)
- .filter(_ % stepWidth == 0))
- case _ => valuesListToString(
- List(1) ++ List.range(start.evalInt, stop.evalInt + 1)
- .filter(_ % stepWidth == 0))
+ case 1 => List.range(start.evalInt, stop.evalInt + 1)
+ .filter(_ % stepWidth == 0)
+ case _ => List(1) ++ List.range(start.evalInt, stop.evalInt + 1)
+ .filter(_ % stepWidth == 0)
}
}
- case _ => valuesListToString(
- List.range(start.evalInt, stop.evalInt+1)
- .filter(_ % stepWidth == 0))
+ case _ =>
+ List.range(start.evalInt, stop.evalInt + 1)
+ .filter(_ % stepWidth == 0)
}
- }
+ filterList(p, wdc._1, values, param)
+ }
case RangeMul(start, stop, mul) => {
// if step is not evaluable use 1 instead
- mul.isEvaluable match {
+ val values = mul.isEvaluable match {
case true => {
val maxVal = scala.math.log(stop.evalInt)/scala.math.log(mul.evalDouble)
- valuesListToString(
- List.range(start.evalInt, maxVal.toInt+1)
- .map(power => scala.math.pow(mul.evalInt, power).toInt))
+ start.evalInt match{
+ case 1 =>
+ List.range(0, maxVal.toInt+1)
+ .map(power => scala.math.pow(mul.evalInt, power).toInt)
+ case _ =>
+ List.range(start.evalInt, maxVal.toInt+1)
+ .map(power => scala.math.pow(mul.evalInt, power).toInt)
+ }
}
case false =>
- valuesListToString(List.range(start.evalInt, stop.evalInt))
+ List.range(start.evalInt, stop.evalInt)
}
+
+ // filtering
+ filterList(p, wdc._1, values, param)
}
- case _ => {
- println("Not yet implemented")
- ""
- }
+
+ case _ => println("not yet implemented")
+
+ println("name: " + param.name)
+ println("range: " + param.range)
+
+ (List.empty[Int], wdc._1)
}
- // check if we have to generate constraints
- val parameterEntry = tuner.hierarchicalHM match {
- case true => {
- // use constraints
+ // get new element with filtered constraints
+ val newWdc = (constraintsFiltered, wdc._2)
- // get dependencies and constraints from map
- val dependencies = parametersWDC(elem)._2.size match {
- case 0 => "[]"
- case _ => elementListToString(parametersWDC(elem)._2.toList)
- }
+ // write constraints
- val constraints = parametersWDC(elem)._1.size match {
- case 0 => "[]"
- case _ => {
- val constraintsList = new ListBuffer[String]
- parametersWDC(elem)._1.foreach(constraint => {
- // check type of constraint
- val constraintString = constraint match {
- case RangeConstraint(n, r) => {
- val (start, stop, step) = r match {
- case RangeAdd(start, stop, step) => (start, stop, step)
- case RangeMul(start, stop, step) => (start, stop, step)
- case _ => (0, 0, 0) // todo catch other types of ranges
- }
-
- // if stop is PosInf, remove constraint
- // (already catched by the range of parameter)
- stop.toString match {
- case "PosInf" =>{
- val startConstraint = n.toString + " >= " + start
- val stepConstraint = n.toString + " % " + step + " == 0"
-
- startConstraint + " and " + stepConstraint
- }
- case _ => {
- val startConstraint = n.toString + " >= " + start
- val stopConstraint = n.toString + " <= " + stop
- val stepConstraint = n.toString + " % " + step + " == 0"
-
- startConstraint + " and " + stopConstraint + " and " + stepConstraint
- }
- }
-
- }
- case PredicateConstraint(n) => {
- n.toString.contains("/^") match {
- case true => constraint.toString.replace("/^", "/")
- case false => constraint.toString
- }
- }
- }
- constraintsList += constraintString
- })
- elementListToString(constraintsList.filter(elem => elem.size != 0).toList)
- }
- }
+ // get dependencies and constraints from map
+ val dependencies = elementListToString(newWdc._2.toList)
+
+ // get constraints list as string
+ val constraints = constraintsToString(newWdc._1)
+
+ // todo think about why order can change
+
+ // check if we have to generate constraints
+ val parameterEntry = tuner.hmConstraints match {
+ case true => {
val parameterEntry =
- s""" "${elem.name}" : {
+ s""" "${param.name}" : {
| "parameter_type" : "ordinal",
- | "values" : ${parameterRange},
+ | "values" : ${values.mkString("[", ", ", "]")},
| "constraints" : ${constraints},
| "dependencies" : ${dependencies}
| },
@@ -165,9 +140,9 @@ object configFileGeneration {
case false => {
// don't use constraints
val parameterEntry =
- s""" "${elem.name}" : {
+ s""" "${param.name}" : {
| "parameter_type" : "ordinal",
- | "values" : ${parameterRange}
+ | "values" : ${values.mkString("[", ", ", "]")}
| },
|""".stripMargin
@@ -175,7 +150,8 @@ object configFileGeneration {
}
}
parameter += parameterEntry
- })
+
+ }}
// remove last comma
val parameterSection = parameter.dropRight(2) + "\n"
@@ -186,24 +162,84 @@ object configFileGeneration {
|""".stripMargin
val file = header + parameterSection + foot
- println("file: \n" + file )
+
+ println("file: " + file)
+
file
}
- def valuesListToString(list: List[Any]): String = {
- var valuesString = ""
- list.foreach(value => {
- valuesString += value.toString + ", "
+ def parseFromJson(filePath: String, word: String) = {
+ Json.parse(readFile(filePath)).apply(word).toString().replaceAll("\"", "")
+ }
+
+ def constraintsToString(constraints: Set[Constraint]): String = {
+
+ val constraintsList = new ListBuffer[String]
+ constraints.foreach(constraint => {
+ // check type of constraint
+ val constraintsAsString:ListBuffer[String] = constraint match {
+ case RangeConstraint(n, r) => {
+ r match {
+ case RangeAdd(start, stop, step) => {
+
+ // if stop is PosInf, remove constraint
+ // (already catched by the range of parameter)
+ stop match {
+ case PosInf =>{
+ val startConstraint = n.toString + " >= " + start
+ val stepConstraint = n.toString + " % " + step + " == 0"
+
+ startConstraint + " and " + stepConstraint
+ ListBuffer[String](startConstraint, stepConstraint)
+ }
+ case _ => {
+ val startConstraint = n.toString + " >= " + start
+ val stopConstraint = n.toString + " <= " + stop
+ val stepConstraint = n.toString + " % " + step + " == 0"
+
+ // startConstraint + " and " + stopConstraint + " and " + stepConstraint
+ ListBuffer[String](startConstraint, stopConstraint, stepConstraint)
+ }
+ }
+ }
+ case RangeMul(start, stop, step) => {
+ // if stop is PosInf, remove constraint
+ // (already catched by the range of parameter)
+ stop match {
+ case PosInf =>{
+ val startConstraint = n.toString + " >= " + start
+ val stepConstraint = n.toString // todo convert range mul constraint into formula
+
+ startConstraint + " and " + stepConstraint
+ ListBuffer[String](startConstraint, stepConstraint)
+ }
+ case _ => {
+ val startConstraint = n.toString + " >= " + start
+ val stopConstraint = n.toString + " <= " + stop
+ val stepConstraint = n.toString + " % " + step + " == 0"
+
+ // startConstraint + " and " + stopConstraint + " and " + stepConstraint
+ ListBuffer[String](startConstraint, stopConstraint, stepConstraint)
+ }
+ }
+ }
+ case _ => (0, 0, 0) // todo catch other types of ranges
+ ListBuffer[String]()
+ }
+ }
+ case PredicateConstraint(n) => ListBuffer[String](n.toString.replace("/^", "/"))
+ }
+// constraintsAsString foreach(elem => constraintsList += elem)
+ constraintsList ++= constraintsAsString
})
- "[" + valuesString.dropRight(2) + "]"
+ elementListToString(constraintsList.filter(elem => elem.size != 0).toList)
}
def elementListToString(list: List[Any]): String = {
- var valuesString = ""
- list.foreach(value => {
- valuesString += "\"" + value.toString + "\"" + ", "
- })
- "[" + valuesString.dropRight(2) + "]"
+ list.size match {
+ case 0 => "[]"
+ case _ => list.mkString("[\"", "\", \"", "\"]")
+ }
}
def distributeConstraints(parameters: Parameters,
@@ -300,6 +336,35 @@ object configFileGeneration {
output.toSeq.sortBy(_.name)
}
+ def filterList(p: Parameters, constraints: Set[Constraint], values:List[Int], param: NatIdentifier): (List[Int], Set[Constraint]) = {
+ val constraintsFiltered:
+ scala.collection.mutable.Set[Constraint] = constraints.to(collection.mutable.Set)
+
+ // check for each value if all constraints pass or are not evaluable
+ val valuesFiltered = values.filter(value => {
+ constraints.forall(constraint => {
+ val params = getParametersFromConstraint(p, constraint)
+ // if occurring parameter in constraint matches given parameter
+ // try to evaluate this constraint
+ params.size match {
+ case 1 => params.last.name match {
+ case param.name => {
+ // remove constraints from set of constraints
+ constraintsFiltered.remove(constraint)
+
+ // check constraint for this value
+ constraint.substitute(Map(TuningParameter(param.name.substring(6)) -> value))
+ .isSatisfied()
+ }
+ case _ => true
+ }
+ case _ => true
+ }
+ })
+ })
+ (valuesFiltered, constraintsFiltered.toSet)
+ }
+
// function to check cycle in parameter dependencies
def check_no_cycle(distribution: Map[NatIdentifier,
(Set[constraints.Constraint], Set[NatIdentifier])]
diff --git a/src/main/scala/rise/autotune/constraints.scala b/src/main/scala/rise/autotune/constraints.scala
index 7e2137ec5..49912f650 100644
--- a/src/main/scala/rise/autotune/constraints.scala
+++ b/src/main/scala/rise/autotune/constraints.scala
@@ -43,14 +43,6 @@ object constraints {
def checkConstraints(constraints: Set[Constraint], values: Map[NatIdentifier, Nat]): Boolean = {
val map = values.asInstanceOf[Map[ArithExpr, ArithExpr]]
-// println("\n")
-// constraints.foreach(elem => {
-// val const = elem.substitute(map)
-// val sat = const.isSatisfied()
-// println("const: " + const)
-// println("sat: " + sat)
-// })
-// println("\n")
constraints.forall(c => c.substitute(map).isSatisfied())
}
diff --git a/src/main/scala/rise/autotune/errors.scala b/src/main/scala/rise/autotune/errors.scala
index 362e5cd31..2b6fc6ead 100644
--- a/src/main/scala/rise/autotune/errors.scala
+++ b/src/main/scala/rise/autotune/errors.scala
@@ -2,7 +2,6 @@ package rise.autotune
sealed trait AutoTuningErrorLevel
-case object NO_ERROR extends AutoTuningErrorLevel
case object CONSTRAINTS_ERROR extends AutoTuningErrorLevel
case object SUBSTITUTION_ERROR extends AutoTuningErrorLevel
case object CODE_GENERATION_ERROR extends AutoTuningErrorLevel
@@ -10,3 +9,5 @@ case object COMPILATION_ERROR extends AutoTuningErrorLevel
case object EXECUTION_ERROR extends AutoTuningErrorLevel
case class AutoTuningError(errorLevel: AutoTuningErrorLevel, message: Option[String])
+
+
diff --git a/src/main/scala/rise/autotune/execution.scala b/src/main/scala/rise/autotune/execution.scala
index 869fec58d..841ae26bc 100644
--- a/src/main/scala/rise/autotune/execution.scala
+++ b/src/main/scala/rise/autotune/execution.scala
@@ -3,75 +3,235 @@ package rise.autotune
import rise.core.Expr
import util.ExecuteOpenCL.{includes, libDirs, libs, platformPath}
import util.{Time, TimeSpan, createTempFile, gen, writeToTempFile}
+
+import java.util.concurrent.ExecutionException
+import scala.collection.mutable.ListBuffer
import scala.language.postfixOps
import scala.sys.process._
+sealed trait RuntimeStatistic
+case object Median extends RuntimeStatistic
+case object Minimum extends RuntimeStatistic
+
+sealed trait FailureMode
+case object `-1` extends FailureMode
+case object IntMax extends FailureMode
+
+case class ExecutionResult(runtime: Either[AutoTuningError, TimeSpan[Time.ms]],
+ codegenTime: Option[TimeSpan[Time.ms]],
+ compilationTime: Option[TimeSpan[Time.ms]],
+ executionTime: Option[TimeSpan[Time.ms]],
+ )
+
object execution {
+ var best:Option[Double] = None
- def execute(e: Expr,
- main: String,
- timeouts: Timeouts)
- : (Option[TimeSpan[Time.ms]], AutoTuningError) = {
+ // logger to avoid printing of stderr
+ val logger = new ProcessLogger {
+ def out(s: => String): Unit = s
+ def err(s: => String): Unit = s
+ def buffer[T](f: => T): T = f
+ }
- val m = autoTuningUtils.runWithTimeout(
- timeouts.codgenerationTimeout)(gen.opencl.hosted.fromExpr(e)
- )
- m match {
- case Some(_) => {
- val program = shine.OpenCL.Module.translateToString(m.get) + main
+ def execute(expression: Expr,
+ hostCode: HostCode,
+ timeouts: Timeouts,
+ executionIterations: Int,
+ speedupFactor: Double,
+ execution: RuntimeStatistic)
+ : ExecutionResult = {
+
+ val codegenStart = System.currentTimeMillis()
+
+ val codegenResult = try {
+
+ // run code-generation with timeout
+ val codgenResult = autoTuningUtils.runWithTimeout(
+ timeouts.codegenerationTimeout)(gen.opencl.hosted("fun").fromExpr(expression))
+
+ // check if timeout was triggered
+ codgenResult match {
+ case Some(_) => Right(codgenResult.get)
+ case None => Left(
+ AutoTuningError(
+ CODE_GENERATION_ERROR, Some("timeout after: " + timeouts.codegenerationTimeout)
+ )
+ )
+ }
+ } catch {
+ case e:Throwable =>
+ Left(AutoTuningError(CODE_GENERATION_ERROR, Some(e.getCause.getMessage)))
+ }
+
+ val codegenTime = TimeSpan.inMilliseconds((System.currentTimeMillis() - codegenStart).toDouble)
+
+ codegenResult match {
+ case Right(generatedModule) => {
+
+ val program =
+ s"""
+ |${shine.OpenCL.Module.translateToString(generatedModule)}
+ |
+ |int main(int argc, char** argv) {
+ | Context ctx = createDefaultContext();
+ | fun_t fun;
+ | fun_init(ctx, &fun);
+ |
+ | ${hostCode.init}
+ |
+ | int iterations = atoi(argv[1]);
+ | for (int sample = 0; sample < iterations; sample++) {
+ | ${hostCode.compute}
+ | }
+ | ${hostCode.finish}
+ | fun_destroy(ctx, &fun);
+ | destroyContext(ctx);
+ | return EXIT_SUCCESS;
+ |}
+ |""".stripMargin
+
+ assert(executionIterations > 0)
// execute program
- executeWithRuntime(
+ val result = executeWithRuntime(
program,
"zero_copy",
timeouts.compilationTimeout,
- timeouts.executionTimeout
+ timeouts.executionTimeout,
+ executionIterations,
+ speedupFactor,
+ execution
)
+
+ ExecutionResult(
+ runtime = result._1,
+ codegenTime = Some(codegenTime),
+ compilationTime = result._2,
+ executionTime = result._3)
}
- case None => (
- None,
- AutoTuningError(
- CODE_GENERATION_ERROR,
- Some("timeout after: " + timeouts.codgenerationTimeout)
+ case Left(error) =>
+ ExecutionResult(
+ runtime = Left(error),
+ codegenTime = Some(codegenTime),
+ compilationTime = None,
+ executionTime = None
)
- )
}
}
def executeWithRuntime(code: String,
buffer_impl: String,
- compilationTimeout: Long, executionTimeout: Long)
- : (Option[TimeSpan[Time.ms]], AutoTuningError) = {
+ compilationTimeout: Long,
+ executionTimeout: Long,
+ executionIterations: Int,
+ speedupFactor: Double,
+ execution: RuntimeStatistic)
+ : (
+ Either[AutoTuningError, TimeSpan[Time.ms]], // runtime or error
+ Option[TimeSpan[Time.ms]], // compilation time
+ Option[TimeSpan[Time.ms]] // execution time
+ ) = {
val src = writeToTempFile("code-", ".c", code).getAbsolutePath
val bin = createTempFile("bin-", "").getAbsolutePath
val sources = s"$src ${platformPath}buffer_$buffer_impl.c ${platformPath}ocl.c"
+
+ val compilationStart = System.currentTimeMillis()
try {
- (s"timeout ${compilationTimeout/1000}s " +
+ (s"timeout ${compilationTimeout.toDouble/1000.toDouble}s " +
s"clang -O2 $sources $includes -o $bin $libDirs $libs -Wno-parentheses-equality" !!)
} catch {
case e: Throwable => {
- println("compile error: " + e)
-
- (None, AutoTuningError(COMPILATION_ERROR, Some(e.toString)))
+ val compilationTime = (System.currentTimeMillis() - compilationStart).toDouble
+ (
+ Left(
+ AutoTuningError(
+ COMPILATION_ERROR,
+ Some(e.toString)
+ )
+ ),
+ Some(TimeSpan.inMilliseconds(compilationTime)),
+ None
+ )
}
}
+ val compilationTime = TimeSpan.inMilliseconds(
+ System.currentTimeMillis().toDouble - compilationStart
+ )
+ val executionStart = System.currentTimeMillis()
try{
- val result = (s"timeout ${executionTimeout/1000}s runtime/clap_wrapper.sh $bin" !!)
- val runtime = getRuntimeFromClap(result)
- (Some(runtime), AutoTuningError(NO_ERROR, None))
+ // execute once to check speedup factor
+ val result = (s"timeout " +
+ s"${(executionTimeout*1).toDouble/1000.toDouble}s " +
+ s"runtime/clap_wrapper.sh $bin 1" !!(logger))
+ val runtimes = getRuntimeFromClap(result)
+
+ // check if speedup condition is met or current best is not initialized
+ val repeat = best match {
+ case Some(bestValue) => runtimes(0).value < bestValue * speedupFactor
+ case None => true
+ }
+
+ // repeat execution with execution iterations
+ val runtime = repeat match {
+ case true => {
+
+ // repeat execution with execution iterations
+ val result = (s"timeout " +
+ s"${(executionTimeout*executionIterations).toDouble/1000.toDouble}s " +
+ s"runtime/clap_wrapper.sh $bin $executionIterations" !!(logger))
+ val runtimes = getRuntimeFromClap(result)
+
+ execution match {
+ case Median =>
+ executionIterations match {
+ case 1 => runtimes.apply(0)
+ case _ => runtimes.sorted.apply(executionIterations/2)
+ }
+ case Minimum => runtimes.min
+ }
+ }
+ case false => runtimes(0)
+ }
+
+ // update or init global best
+ best = best match{
+ case Some(value) => runtime.value < value match {
+ case true => Some(runtime.value)
+ case false => best
+ }
+ case None => Some(runtime.value)
+ }
+
+ val executionTime = TimeSpan.inMilliseconds(
+ (System.currentTimeMillis() - executionStart).toDouble
+ )
+
+ (
+ Right(runtime),
+ Some(compilationTime),
+ Some(executionTime)
+ )
} catch {
// todo check error codes here
case e: Throwable => {
- println("execution error: " + e)
-
- (None, AutoTuningError(EXECUTION_ERROR, Some(e.toString)))
+ val executionTime = TimeSpan.inMilliseconds(
+ (System.currentTimeMillis() - executionStart).toDouble
+ )
+ (
+ Left(AutoTuningError(
+ EXECUTION_ERROR,
+ Some(e.toString)
+ )),
+ Some(compilationTime),
+ Some(executionTime)
+ )
}
}
}
- def getRuntimeFromClap(s: String): TimeSpan[Time.ms] = {
+ def getRuntimeFromClap(s: String): Seq[TimeSpan[Time.ms]] = {
// convert input String to array of Strings (line-wise)
val sArray = s.split("\n")
@@ -84,11 +244,16 @@ object execution {
// load xml as string and compute runtime
val clapResult = scala.xml.XML.loadString(sCorrect)
- val start = (clapResult \\ "@start").toString().toLong
- val end = (clapResult \\ "@end").toString().toLong
- val runtime = end - start
- // convert to ms
- TimeSpan.inMilliseconds(runtime.toDouble/1000000)
+ val startSeq = (clapResult \\ "@start")
+ val endSeq = (clapResult \\ "@end")
+
+ val runtimes = (startSeq zip endSeq).map(timespan => {
+ TimeSpan.inMilliseconds(
+ (timespan._2.toString().toLong - timespan._1.toString().toLong)
+ .toDouble/1000000)
+ })
+
+ runtimes
}
}
diff --git a/src/main/scala/rise/autotune/package.scala b/src/main/scala/rise/autotune/package.scala
index c528fa09d..e752adb94 100644
--- a/src/main/scala/rise/autotune/package.scala
+++ b/src/main/scala/rise/autotune/package.scala
@@ -1,6 +1,6 @@
package rise
-import arithexpr.arithmetic.RangeUnknown
+import arithexpr.arithmetic.{ArithExpr, RangeUnknown}
import rise.autotune.configFileGeneration._
import rise.autotune.constraints._
import rise.autotune.execution._
@@ -19,22 +19,61 @@ import scala.sys.process._
package object autotune {
- case class Timeouts(codgenerationTimeout: Long, compilationTimeout: Long, executionTimeout: Long)
- case class Tuner(main: String,
- iterations: Int = 100,
- name: String = "RISE",
- output: String = "autotuning",
- timeouts: Timeouts = Timeouts(5000, 5000, 5000),
- configFile: Option[String] = None,
- hierarchicalHM: Boolean = false)
-
- case class Sample(parameters: Map[NatIdentifier, Nat],
- runtime: Option[TimeSpan[Time.ms]],
- timestamp: Long,
- autoTuningError: AutoTuningError)
-
- // todo add meta information (configuration, times, samples, ...)
- case class TuningResult(samples: Seq[Sample])
+ case class Tuner(hostCode: HostCode, // defines necessary host-code to execute program
+ inputSizes: Seq[Nat] = Seq(), // todo think about multi-dimensional inputs
+ samples: Int = 100, // number of parameter configurations (samples) to evaluate
+ name: String = "RISE", // todo this has to match name in config file!
+ output: String = "autotuning", // folder to store output files in
+ timeouts: Timeouts = Timeouts(5000, 5000, 5000), // timeouts for codegen, compilation and execution
+ executionIterations: Int = 10, // defines, how many times the program is executed to determine the runtime a sample
+ runtimeStatistic: RuntimeStatistic = Median, // specifies, how to determine the runtime from multiple iterations (Median/Minimum)
+ speedupFactor: Double = 100, // defines at which threshold the iterations are dropped, if the execution is slow compared to current best
+ configFile: Option[String] = None, // specifies the location of a config-file, otherwise, a config file is generated
+ hmConstraints: Boolean = false, // enable constraints feature in HM (experimental)
+ saveToFile: Boolean = false,
+ failureMode: FailureMode = IntMax
+ )
+
+ // necessary host-code parts to execute the program
+ case class HostCode(init: String, // define and initialize input/output (buffers)
+ compute: String, // call the function with the input and output
+ finish: String) // check output, destroy input/output buffers
+
+ // timeouts for sub-parts of the evaluation of a parameter configuration (sample)
+ case class Timeouts(codegenerationTimeout: Long, // timeout for code-generation part
+ compilationTimeout: Long, // timeout for compilation part
+ executionTimeout: Long // timeout for execution part
+ )
+
+ // result of a complete tuning run and used tuner
+ case class TuningResult(samples: Seq[Sample],
+ tuner: Tuner
+ )
+
+ // tuning sample representing result of one specific parameter configuration
+ case class Sample(parameters: Map[NatIdentifier, Nat], // specific parameter configuration
+ runtime: Either[AutoTuningError, TimeSpan[Time.ms]], // runtime or error
+ timestamp: Long, // timestamp of sample
+ tuningTimes: TuningTimes // durations of sub-parts
+ )
+
+ // durations of sub-parts of a tuning sample
+ case class TuningTimes(total: Option[TimeSpan[Time.ms]], // total time
+ codegen: Option[TimeSpan[Time.ms]], // duration of code-generation part
+ compilation: Option[TimeSpan[Time.ms]], // duration of compilation part
+ execution: Option[TimeSpan[Time.ms]] // duration of execution part
+ )
+
+ case class TuningStatistics(
+ name: String,
+ totalSamples: Int,
+ executionIterations: Int,
+ totalExecutions: Int,
+ totalDuration: TimeSpan[Time.s],
+ averageDuration: TimeSpan[Time.s]
+
+ )
+
type Parameters = Set[NatIdentifier]
// should we allow tuning params to be substituted during type inference?
@@ -48,16 +87,35 @@ package object autotune {
val start = System.currentTimeMillis()
val parameters = collectParameters(e)
+
+ // inject input sizes into constraints
+ val inputs = getInputs(e)
+ val inputMap = (inputs zip tuner.inputSizes).toMap
val constraints = collectConstraints(e, parameters)
- ("mkdir -p " + tuner.output !!)
+ .map(constraint => constraint.substitute(inputMap.asInstanceOf[Map[ArithExpr, ArithExpr]]))
+
+ if(tuner.saveToFile){
+ ("mkdir -p " + tuner.output + "/" + tuner.name !!)
+ ("mkdir -p " + tuner.output + "/" + tuner.name + "_hm" !!)
+ ("mkdir -p " + tuner.output + "/" + "log" !!)
+ }
// generate json if necessary
tuner.configFile match {
case None =>
println("generate configuration file")
+
+ val filePath = tuner.saveToFile match{
+ case true => tuner.output + "/" + tuner.name + ".json"
+ case false => {
+ ("mkdir -p tmp" !!)
+ "/tmp/" + tuner.name + ".json"
+ }
+ }
+
val file = new PrintWriter(
new FileOutputStream(
- new File(tuner.output + "/" + tuner.name + ".json"), false))
+ new File(filePath), false))
file.write(generateJSON(parameters, constraints, tuner))
file.close()
case _ => println("use given configuration file")
@@ -68,48 +126,67 @@ package object autotune {
// compute function value as result for hypermapper
val computeSample: (Array[String], Array[String]) => Sample = (header, parametersValues) => {
+ val totalStart = System.currentTimeMillis()
+
val parametersValuesMap: Map[NatIdentifier, Nat] = header.zip(parametersValues).map { case (h, p) =>
- NatIdentifier(h) -> (p.toInt: Nat)
+ NatIdentifier(h) -> (p.toFloat.toInt: Nat)
}.toMap
if (checkConstraints(constraints, parametersValuesMap)) {
- println("constraints true")
// execute
val result = execute(
- rise.core.substitute.natsInExpr(parametersValuesMap.toMap[Nat, Nat], e), tuner.main, tuner.timeouts)
- result._1 match {
- case Some(_) =>
- Sample(parametersValuesMap, result._1, System.currentTimeMillis() - start, result._2)
- case None =>
- Sample(parametersValuesMap, result._1, System.currentTimeMillis() - start, result._2)
- }
+ rise.core.substitute.natsInExpr(parametersValuesMap.toMap[Nat, Nat], e),
+ tuner.hostCode,
+ tuner.timeouts,
+ tuner.executionIterations,
+ tuner.speedupFactor,
+ tuner.runtimeStatistic
+ )
+ val totalTime = Some(TimeSpan.inMilliseconds(
+ (System.currentTimeMillis() - totalStart).toDouble)
+ )
+ Sample(
+ parameters = parametersValuesMap,
+ runtime = result.runtime,
+ timestamp = System.currentTimeMillis() - start,
+ tuningTimes = TuningTimes(
+ totalTime, result.codegenTime, result.compilationTime, result.executionTime)
+ )
} else {
- println("constraints false")
+ val totalTime = Some(TimeSpan.inMilliseconds((System.currentTimeMillis() - totalStart).toDouble))
Sample(
- parametersValuesMap,
- None,
- System.currentTimeMillis() - start,
- AutoTuningError(CONSTRAINTS_ERROR, None)
+ parameters = parametersValuesMap,
+ runtime = Left(AutoTuningError(CONSTRAINTS_ERROR, None)),
+ timestamp = System.currentTimeMillis() - start,
+ tuningTimes = TuningTimes(totalTime, None, None, None)
)
}
}
val configFile = tuner.configFile match {
- case Some(filename) => os.Path.apply(filename)
- case None => os.pwd / tuner.output / (tuner.name + ".json")
+ case Some(filename) =>
+ filename.substring(0, 1) match {
+ case "/" => os.Path.apply(filename)
+ case _ => os.Path.apply(os.pwd.toString() + "/" + filename)
+ }
+ case None => os.Path.apply(
+ tuner.saveToFile match {
+ case true => os.pwd.toString() + "/" + tuner.output + "/" + tuner.name + ".json"
+ case false => "/tmp/" + tuner.name + ".json"
+ }
+ )
}
println("configFile: " + configFile)
- // check if hypermapper is installed and config file exists
- assert(
- (os.isFile(os.Path.apply("/usr/local/bin/hypermapper"))
- || os.isFile(os.Path.apply("/usr/bin/hypermapper")))
- && os.isFile(configFile)
- )
+ // check if hypermapper is installed
+ ("which hypermapper" !!)
+
+ // check if config file exists
+ assert(os.isFile(configFile))
val hypermapper = os.proc("hypermapper", configFile).spawn()
- var i = 0
+ var i = 1
// main tuning loop
var samples = new ListBuffer[Sample]()
var done = false
@@ -139,25 +216,52 @@ package object autotune {
// read in parameters values
val parametersValues = hypermapper.stdout.readLine().split(",").map(x => x.trim())
// compute sample (including function value aka runtime)
+ print("[" + i.toString + "/" + numberOfEvalRequests + "] : ")
val sample = computeSample(header, parametersValues)
+ println(sample.runtime)
+ println(sample)
+ println()
+ i += 1
// append sample to Samples
samples += sample
// append response
sample.runtime match {
- case None => response += s"${parametersValues.mkString(",")},-1,False\n"
- case Some(value) =>
- response += s"${parametersValues.mkString(",")},${value.value},True\n"
+ case Left(value) =>
+ // make sure to response int values
+
+ // check output mode
+ val runtime: String = tuner.failureMode match {
+ case `-1` => "-1"
+ case IntMax => "2147483647"
+ }
+
+ response += s"${parametersValues.map(x => x.toFloat.toInt).mkString(",")},${runtime},False\n"
+ case Right(value) =>
+ // make sure to response int values
+ response += s"${parametersValues.map(x => x.toFloat.toInt).mkString(",")},${value.value},True\n"
}
}
- print(s"Response: $response")
+
// send response to Hypermapper
hypermapper.stdin.write(response)
hypermapper.stdin.flush()
- case error => println("error: " + error)
+ case message => println("message: " + message)
}
}
- TuningResult(samples.toSeq)
+ println("tuning finished")
+
+ val tuningResult = TuningResult(samples.toSeq, tuner)
+ saveTuningResult(tuningResult)
+
+ tuningResult
+ }
+
+ def getUniqueFilepath(path: String, ending: String): String = {
+ new File(path).exists() match {
+ case true => path.substring(0, path.length - ending.length) + "_" + System.currentTimeMillis() + ending
+ case false => path
+ }
}
// wrap ocl run to a function
@@ -170,15 +274,16 @@ package object autotune {
// depFun(x => e)
case dl@DepLambda(kind, x, e) =>
DepLambda(kind, x, wrapOclRun(localSize, globalSize)(e))(dl.t)
- case e => oclRun(localSize, globalSize)(e)
+ case e =>
+ oclRun(localSize, globalSize)(e)
}
}
def getBest(samples: Seq[Sample]): Option[Sample] = {
val best = samples.reduceLeft(min)
best.runtime match {
- case Some(_) => Some(best)
- case None => None
+ case Right(_) => Some(best)
+ case Left(_) => None
}
}
@@ -194,18 +299,117 @@ package object autotune {
rise.core.substitute.natsInExpr(sample.parameters.toMap[Nat, Nat], e)
}
+ def getDuration(tuningResult: TuningResult): TimeSpan[Time.ms]= {
+ val duration = tuningResult.samples.apply(tuningResult.samples.size).timestamp -
+ tuningResult.samples.apply(0).timestamp
+
+ TimeSpan.inMilliseconds(duration.toDouble)
+ }
+
+ def getSamples(tuningResult: TuningResult): Int = {
+ tuningResult.samples.size
+ }
+
+ def saveTuningResult(tuningResult: TuningResult) = {
+ val tuner = tuningResult.tuner
+
+ // save results to file
+ if(tuner.saveToFile) {
+
+ // get unique filepath
+ val path = tuner.output + "/" + tuner.name + "/" + tuner.name + ".csv"
+ val file = new File(path)
+ val timeAppendix = if (file.exists()) {
+ "_" + System.currentTimeMillis().toString
+ } else {
+ ""
+ }
+
+ // save samples to file
+ saveSamples(
+ tuner.output + "/" + tuner.name + "/" + tuner.name + timeAppendix + ".csv",
+ tuningResult
+ )
+
+ // save hm output file
+ ("mv " + tuner.name + "_output_samples.csv" + " " +
+ tuner.output + "/" + tuner.name + "_hm/" + tuner.name + timeAppendix + "_hm" + ".csv" !!)
+
+ // save logfile and configfile
+ if(tuner.configFile.isDefined) {
+
+ // parse logfile name from json or use default name
+ val logfile = try {
+ parseFromJson(tuner.configFile.get, "log_file")
+ } catch {
+ case e: NoSuchElementException => "hypermapper_logfile.log"
+ }
+
+ // move logfile to output folder
+ ("mv " + logfile + " " +
+ tuner.output + "/log/" + logfile.substring(0, logfile.length - 4) + timeAppendix + ".log" !!)
+
+ // copy config file to output folder
+ ("cp " + tuner.configFile.get + " " + tuner.output !!)
+ } else {
+
+ // move logfile to output folder
+ ("mv " + tuner.name + ".log" + " " +
+ tuner.output + "/log/" + tuner.name + timeAppendix + ".log" !!) // get unique filename
+
+ }
+
+ // create plots
+ plotTuning(tuner)
+
+ } else {
+ // remove logfile and generated config file
+ if(tuner.configFile.isDefined){
+
+ val logfile = try {
+ parseFromJson(tuner.configFile.get, "log_file")
+ } catch {
+ case e: NoSuchElementException => "hypermapper_logfile.log"
+ }
+
+ ("rm " + logfile !!)
+
+ }else{
+
+ ("rm " + tuner.name + ".log" !!)
+ ("rm " + "/tmp/" + tuner.name + ".json" !!)
+
+ }
+ }
+
+ // todo save meta
+
+ }
+
// write tuning results into csv file
- def saveSamples(path: String, tuningResult: TuningResult): Unit = {
+ def saveSamples(path: String, tuningResult: TuningResult): String = {
+ // create unique filepath
+ val file = new File(path)
+ val uniqueFilepath = if (file.exists()) {
+ val timeAppendix = System.currentTimeMillis().toString
+ path.substring(0, path.length - 4) + "_" + timeAppendix + ".csv"
+ } else {
+ path
+ }
+
// write header
var header = ""
tuningResult.samples.head.parameters.foreach {
case (id: NatIdentifier, _:Nat) => header += id.name + ","
case _ => throw Exception("This should not happen")
}
+
header += "runtime" + ","
- header += "error level" + ","
- header += "error message" + ","
- header += "timestamp"
+ header += "timestamp" + ","
+ header += "total" + ","
+ header += "code generation" + ","
+ header += "compilation" + ","
+ header += "execution" + ","
header += "\n"
// write content
@@ -218,47 +422,112 @@ package object autotune {
})
// write runtime
- sample.runtime match {
- case Some(value) => content += value.value.toString + ","
- case None => content += "-1" + ","
- }
+ sample.runtime match{
+ case Right(runtime) => content += runtime.toString + ","
+ case Left(error) =>
- // write error level
- content += sample.autoTuningError.errorLevel.toString + ","
+ val errorMessage = error.message match {
+ case None => ""
+ case Some(value) => ": " + value
+ }
+
+ content += error.errorLevel.toString + errorMessage + ","
- // write error message
- sample.autoTuningError.message match {
- case Some(value) => content += value + ","
- case None => content += "" + ","
}
// write timestamp
- content += sample.timestamp
+ content += sample.timestamp.toString + ","
+
+ sample.tuningTimes.total match {
+ case Some(value) => content += value.value.toString + ","
+ case None => content += "-1" + ","
+ }
+ sample.tuningTimes.codegen match {
+ case Some(value) => content += value.value.toString + ","
+ case None => content += "-1" + ","
+ }
+ sample.tuningTimes.compilation match {
+ case Some(value) => content += value.value.toString + ","
+ case None => content += "-1" + ","
+ }
+ sample.tuningTimes.execution match {
+ case Some(value) => content += value.value.toString + ","
+ case None => content += "-1" + ","
+ }
// finish line
content += "\n"
})
- writeToPath(path, header + content)
+ writeToPath(uniqueFilepath, header + content)
+
+
+ uniqueFilepath
}
+ def plotTuning(tuner: Tuner) = {
+
+ // get config file
+ val configFile: String = tuner.configFile match {
+ case Some(value) => value
+ case None => tuner.output + "/" + tuner.name + ".json"
+ }
+
+ // plot results using hypermapper
+ ("hm-plot-optimization-results " +
+ "-j " + configFile + " " +
+ "-i " + tuner.output + "/" + tuner.name + "_hm" + " " +
+ "-o" + tuner.output + "/" + tuner.name + ".pdf" + " " +
+ "-log --y_label \"Log Runtime(ms)\"" !!)
+ }
+
+ // todo finish implementation
+ def saveMeta(path: String, tuningResult: TuningResult, tuner: Tuner): String = {
+
+ // todo save tuner information to file
+
+ // todo collect statistics from tuningResult
+ val duration = (tuningResult.samples.apply(tuningResult.samples.size).timestamp - tuningResult.samples.apply(0).timestamp)
+ val samples = tuningResult.samples.size
+
+ // save statistics to csv file (don't overwrite -> append)
+
+
+ // return unique filename
+ ""
+ }
+
+
+ // helper functions
private def min(s1: Sample, s2: Sample): Sample = {
s1.runtime match {
- case Some(s1Runtime) =>
+ case Right(s1Runtime) =>
s2.runtime match {
- case Some(s2Runtime) =>
+ case Right(s2Runtime) =>
if (s1Runtime.value < s2Runtime.value) {
s1
} else {
s2
}
- case None => s1
+ case Left(_) => s1
}
- case None =>
+ case Left(_) =>
s2.runtime match{
- case Some(_) => s2
- case None => s1
+ case Right(_) => s2
+ case Left(_) => s1
}
}
}
+
+ def getInputs(e: Expr): Seq[NatIdentifier] = {
+ getInputsRec(Seq.empty[NatIdentifier], e)
+ }
+
+ def getInputsRec(inputs: Seq[NatIdentifier], e: Expr): Seq[NatIdentifier] = {
+ e match {
+ case DepLambda(NatKind, n: NatIdentifier, subexpr) => getInputsRec(inputs :+ n, subexpr)
+ case _ => inputs
+ }
+ }
+
}
diff --git a/src/test/scala/rise/autotune/TestAutotuning.scala b/src/test/scala/rise/autotune/TestAutotuning.scala
new file mode 100644
index 000000000..a4ae57488
--- /dev/null
+++ b/src/test/scala/rise/autotune/TestAutotuning.scala
@@ -0,0 +1,114 @@
+package rise.autotune
+
+import arithexpr.arithmetic._
+import rise.autotune
+import rise.core.DSL._
+import rise.core._
+import rise.core.primitives.{let => _, _}
+import rise.core.types.{NatIdentifier, _}
+import shine.OpenCL.{GlobalSize, LocalSize}
+
+class TestAutotuning extends test_util.Tests {
+
+ test("collect parameters") {
+ val params = autotune.constraints.collectParameters(util.expressions.convolution.convolutionOclGsLsWrap)
+ assert(params.find(IsTuningParameter("vec")).get.range == RangeAdd(1, 32, 1))
+ assert(params.find(IsTuningParameter("tile")).get.range == RangeAdd(4, 32, 1))
+ assert(params.find(IsTuningParameter("ls0")).get.range == RangeUnknown)
+ assert(params.find(IsTuningParameter("ls1")).get.range == RangeUnknown)
+ assert(params.find(IsTuningParameter("gs0")).get.range == RangeUnknown)
+ assert(params.find(IsTuningParameter("gs1")).get.range == RangeUnknown)
+ assert(params.size == 6)
+ }
+
+ test("substitute parameters") {
+ val e: Expr = util.expressions.convolution.convolution(32)
+ val constraints = autotune.constraints.collectConstraints(e,
+ autotune.constraints.collectParameters(e))
+ println("constraints: \n" + constraints)
+
+ val badParameters1 = Map(
+ TuningParameter("vec") -> (5: Nat),
+ TuningParameter("tile") -> (15: Nat)
+ )
+ assert(!autotune.constraints.checkConstraints(constraints, badParameters1))
+
+ val badParameters2 = Map(
+ TuningParameter("vec") -> (4: Nat),
+ TuningParameter("tile") -> (13: Nat)
+ )
+ assert(!autotune.constraints.checkConstraints(constraints, badParameters2))
+
+ /* FIXME: there is no `n >= tile` constraint collected
+ val badParameters3 = Map(
+ TuningParameter("vec") -> (8: Nat),
+ TuningParameter("tile") -> (64: Nat)
+ )
+ assert(!autotune.checkConstraints(constraints, badParameters3))
+ */
+
+ val goodParameters = Map(
+ TuningParameter("vec") -> (4: Nat),
+ TuningParameter("tile") -> (16: Nat)
+ )
+ assert(autotune.constraints.checkConstraints(constraints, goodParameters))
+ rise.core.substitute.natsInExpr(goodParameters.toMap[Nat, Nat], e)
+ }
+
+ test("wrapOclRun") {
+ val wrapped = wrapOclRun(LocalSize(1), GlobalSize(32))(util.expressions.convolution.convolution)
+ assert(util.expressions.convolution.convolutionOcl.toExpr =~= wrapped)
+
+ val e = (wrapped: ToBeTyped[Expr]) (32)
+ assert(util.expressions.convolution.convolutionOcl(32).toExpr =~= e.toExpr)
+ }
+
+ test("search") {
+ // test full tuning run
+ val e: Expr = util.expressions.convolution.convolutionOcl
+
+ val tuner = Tuner(
+ name = "convolution",
+ hostCode = util.hostcode.convolution(32),
+ inputSizes = Seq(32),
+ output = "autotuning/convolution", // folder to store output files in
+ saveToFile = true
+ )
+
+ val tuningResult = autotune.search(tuner)(e)
+
+ println("tuningResult: \n")
+ tuningResult.samples.foreach(elem => println(elem))
+
+ val bestSample = autotune.getBest(tuningResult.samples)
+ println("bestSample: \n" + bestSample)
+ }
+
+ // test Hypermapper constraints support
+ // needs access to hypermapper_dev repository
+ ignore("search experimental") {
+ val e: Expr = util.expressions.convolution.convolutionOclGsLs(1024)
+
+ val tuner = Tuner(
+ hostCode = util.hostcode.convolution(1024),
+ samples = 100,
+ name = "RISE",
+ output = "autotuning",
+ timeouts = Timeouts(5000, 5000, 5000),
+ executionIterations = 10,
+ speedupFactor = 100,
+ configFile = None,
+ hmConstraints = false
+ )
+
+ val tuningResult = autotune.search(tuner)(e)
+
+ println("tuningResult: \n")
+ tuningResult.samples.foreach(elem => println(elem))
+
+ val bestSample = autotune.getBest(tuningResult.samples)
+ println("bestSample: \n" + bestSample)
+
+ autotune.saveSamples("autotuning/RISE.csv", tuningResult)
+ }
+}
diff --git a/src/test/scala/rise/autotune/TestConfigFileGeneration.scala b/src/test/scala/rise/autotune/TestConfigFileGeneration.scala
new file mode 100644
index 000000000..10fe329dd
--- /dev/null
+++ b/src/test/scala/rise/autotune/TestConfigFileGeneration.scala
@@ -0,0 +1,292 @@
+package rise.autotune
+
+import arithexpr.arithmetic.{ArithExpr}
+import rise.autotune
+import rise.autotune.configFileGeneration.{check_no_cycle, distributeConstraints}
+import rise.core.{DepLambda, Expr}
+import rise.core.types.{Nat, NatIdentifier, NatKind}
+
+class TestConfigFileGeneration extends test_util.Tests {
+
+ // todo add test for other case
+ test("distribute constraints") {
+
+ val e: Expr = util.expressions.convolution.convolutionOclGsLs(1024)
+ val params = autotune.constraints.collectParameters(e)
+ val constraints = autotune.constraints.collectConstraints(e, params)
+
+ val paramsSorted = params.toSeq.sortBy(_.name)
+ val gs0 = paramsSorted(0)
+ val gs1 = paramsSorted(1)
+ val ls0 = paramsSorted(2)
+ val ls1 = paramsSorted(3)
+ val tile = paramsSorted(4)
+ val vec = paramsSorted(5)
+
+ val constraintsSorted = constraints.toSeq.sortBy(_.toString)
+
+ val gold = Map(
+ gs0 -> (Set(constraintsSorted(3), constraintsSorted(4)), Set(ls0)),
+ gs1 -> (Set(constraintsSorted(5), constraintsSorted(6)), Set(ls1)),
+ ls0 -> (Set(constraintsSorted(7)), Set.empty[NatIdentifier]),
+ ls1 -> (Set(constraintsSorted(8)), Set.empty[NatIdentifier]),
+ tile -> (Set(constraintsSorted(0), constraintsSorted(1), constraintsSorted(9)), Set(vec)),
+ vec -> (Set(constraintsSorted(10), constraintsSorted(11)), Set.empty[NatIdentifier])
+ )
+
+ val distribution = autotune.configFileGeneration.distributeConstraints(params, constraints)
+
+ // check if distribution contains cycle
+ assert(check_no_cycle(distribution))
+
+ // check distribution against gold (which distribution to expect)
+ println("\ndistribution: " )
+ distribution.foreach(println)
+
+ println("\ngold: " )
+ gold.foreach(println)
+
+ var size = 0
+ distribution.foreach(elem => {
+ size += elem._2._1.size
+ assert(gold.apply(elem._1)._1.equals(elem._2._1))
+ assert(gold.apply(elem._1)._2.equals(elem._2._2))
+ })
+
+ // we drop one constraint, which is static
+ assert(size.equals(constraintsSorted.size-1))
+ }
+
+ test("test cycle checker"){
+
+ val emptyConstraints = Set.empty[constraints.Constraint]
+
+ val A = NatIdentifier("A")
+ val B = NatIdentifier("B")
+ val C = NatIdentifier("C")
+
+ // create example with no cycle
+ val distributionNoCycle = scala.collection.mutable.Map[NatIdentifier,
+ (Set[constraints.Constraint], Set[NatIdentifier])]()
+ val dependenciesNoCycleA = Set(B)
+ val dependenciesNoCycleB = Set.empty[NatIdentifier]
+ val dependenciesNoCycleC = Set(A)
+
+ distributionNoCycle(A) = (emptyConstraints, dependenciesNoCycleA)
+ distributionNoCycle(B) = (emptyConstraints, dependenciesNoCycleB)
+ distributionNoCycle(C) = (emptyConstraints, dependenciesNoCycleC)
+
+ assert(check_no_cycle(distributionNoCycle.toMap))
+
+ // create example with cycle
+ val distributionCycle = scala.collection.mutable.Map[NatIdentifier,
+ (Set[constraints.Constraint], Set[NatIdentifier])]()
+ val dependenciesCycleA = Set(B)
+ val dependenciesCycleB = Set(A)
+ val dependenciesCycleC = Set.empty[NatIdentifier]
+
+ distributionCycle(A) = (emptyConstraints, dependenciesCycleA)
+ distributionCycle(B) = (emptyConstraints, dependenciesCycleB)
+ distributionCycle(C) = (emptyConstraints, dependenciesCycleC)
+
+ assert(!check_no_cycle(distributionCycle.toMap))
+
+ // create another example with cycle
+ val distributionCycle2 = scala.collection.mutable.Map[NatIdentifier,
+ (Set[constraints.Constraint], Set[NatIdentifier])]()
+ val dependenciesCycle2A = Set(B)
+ val dependenciesCycle2B = Set(B)
+ val dependenciesCycle2C = Set.empty[NatIdentifier]
+
+ distributionCycle2(A) = (emptyConstraints, dependenciesCycle2A)
+ distributionCycle2(B) = (emptyConstraints, dependenciesCycle2B)
+ distributionCycle2(C) = (emptyConstraints, dependenciesCycle2C)
+
+ assert(!check_no_cycle(distributionCycle2.toMap))
+ }
+
+ test("generateJSON conv") {
+ val e: Expr = util.expressions.convolution.convolution
+
+ val nIdent = e match {
+ case DepLambda(NatKind, n: NatIdentifier, _) => n
+ case _ => ???
+ }
+
+ val n: Nat = 32
+ val map = Map(nIdent -> n)
+
+ val parameters = autotune.constraints.collectParameters(e)
+ val constraints = autotune.constraints.collectConstraints(e, parameters)
+ val constraintsSubstituted = constraints.map(constraint => constraint.substitute(map.asInstanceOf[Map[ArithExpr, ArithExpr]]))
+
+ val tuner = Tuner(
+ hostCode = util.hostcode.convolution(32),
+ inputSizes = Seq(32),
+ samples = 100,
+ name = "RISE",
+ output = "autotuning",
+ timeouts =Timeouts(5000, 5000, 5000),
+ executionIterations = 10,
+ speedupFactor = 100,
+ configFile = None,
+ hmConstraints = false
+ )
+
+ val json = autotune.configFileGeneration.generateJSON(parameters, constraintsSubstituted, tuner)
+
+ // scalastyle:off
+ val gold =
+ """{
+ | "application_name" : "RISE",
+ | "optimization_objectives" : ["runtime"],
+ | "hypermapper_mode" : {
+ | "mode" : "client-server"
+ | },
+ | "log_file" : "RISE.log",
+ | "feasible_output" : {
+ | "enable_feasible_predictor" : true,
+ | "name" : "Valid",
+ | "true_value" : "True",
+ | "false_value" : "False"
+ | },
+ | "design_of_experiment" : {
+ | "doe_type" : "random sampling",
+ | "number_of_samples" : 20
+ | },
+ | "optimization_iterations" : 100,
+ | "input_parameters" : {
+ | "tuned_tile" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
+ | },
+ | "tuned_vec" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [2, 4, 8, 16]
+ | }
+ | }
+ |}
+ |""".stripMargin
+ // scalastyle:on
+
+ println("json: \n" + json)
+
+ println("gold : \n" + gold)
+
+ assert(util.compareConfigFiles(json, gold))
+ }
+
+ test("generateJSON mm"){
+
+ // scalastyle:off
+ val gold =
+ """{
+ | "application_name" : "RISE",
+ | "optimization_objectives" : ["runtime"],
+ | "hypermapper_mode" : {
+ | "mode" : "client-server"
+ | },
+ | "log_file" : "RISE.log",
+ | "feasible_output" : {
+ | "enable_feasible_predictor" : true,
+ | "name" : "Valid",
+ | "true_value" : "True",
+ | "false_value" : "False"
+ | },
+ | "design_of_experiment" : {
+ | "doe_type" : "random sampling",
+ | "number_of_samples" : 100
+ | },
+ | "optimization_iterations" : 100,
+ | "input_parameters" : {
+ | "tuned_v7" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [4, 8, 16, 32, 64, 128, 256, 512, 1024]
+ | },
+ | "tuned_v8" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
+ | },
+ | "tuned_gs0" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024]
+ | },
+ | "tuned_gs1" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024]
+ | },
+ | "tuned_v3" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 284, 288, 292, 296, 300, 304, 308, 312, 316, 320, 324, 328, 332, 336, 340, 344, 348, 352, 356, 360, 364, 368, 372, 376, 380, 384, 388, 392, 396, 400, 404, 408, 412, 416, 420, 424, 428, 432, 436, 440, 444, 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, 488, 492, 496, 500, 504, 508, 512, 516, 520, 524, 528, 532, 536, 540, 544, 548, 552, 556, 560, 564, 568, 572, 576, 580, 584, 588, 592, 596, 600, 604, 608, 612, 616, 620, 624, 628, 632, 636, 640, 644, 648, 652, 656, 660, 664, 668, 672, 676, 680, 684, 688, 692, 696, 700, 704, 708, 712, 716, 720, 724, 728, 732, 736, 740, 744, 748, 752, 756, 760, 764, 768, 772, 776, 780, 784, 788, 792, 796, 800, 804, 808, 812, 816, 820, 824, 828, 832, 836, 840, 844, 848, 852, 856, 860, 864, 868, 872, 876, 880, 884, 888, 892, 896, 900, 904, 908, 912, 916, 920, 924, 928, 932, 936, 940, 944, 948, 952, 956, 960, 964, 968, 972, 976, 980, 984, 988, 992, 996, 1000, 1004, 1008, 1012, 1016, 1020, 1024]
+ | },
+ | "tuned_v4" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024]
+ | },
+ | "tuned_v5" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
+ | },
+ | "tuned_ls0" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024]
+ | },
+ | "tuned_v6" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, 256, 260, 264, 268, 272, 276, 280, 284, 288, 292, 296, 300, 304, 308, 312, 316, 320, 324, 328, 332, 336, 340, 344, 348, 352, 356, 360, 364, 368, 372, 376, 380, 384, 388, 392, 396, 400, 404, 408, 412, 416, 420, 424, 428, 432, 436, 440, 444, 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, 488, 492, 496, 500, 504, 508, 512, 516, 520, 524, 528, 532, 536, 540, 544, 548, 552, 556, 560, 564, 568, 572, 576, 580, 584, 588, 592, 596, 600, 604, 608, 612, 616, 620, 624, 628, 632, 636, 640, 644, 648, 652, 656, 660, 664, 668, 672, 676, 680, 684, 688, 692, 696, 700, 704, 708, 712, 716, 720, 724, 728, 732, 736, 740, 744, 748, 752, 756, 760, 764, 768, 772, 776, 780, 784, 788, 792, 796, 800, 804, 808, 812, 816, 820, 824, 828, 832, 836, 840, 844, 848, 852, 856, 860, 864, 868, 872, 876, 880, 884, 888, 892, 896, 900, 904, 908, 912, 916, 920, 924, 928, 932, 936, 940, 944, 948, 952, 956, 960, 964, 968, 972, 976, 980, 984, 988, 992, 996, 1000, 1004, 1008, 1012, 1016, 1020, 1024]
+ | },
+ | "tuned_ls1" : {
+ | "parameter_type" : "ordinal",
+ | "values" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024]
+ | }
+ | }
+ |}
+ |""".stripMargin
+ // scalastyle:on
+
+ val e: Expr = util.expressions.mm.mmOclGsLsWrapRanges
+
+ // todo find a generic solution?
+ val (nIdent, mIdent, oIdent) = e match {
+ case DepLambda(NatKind, n: NatIdentifier, DepLambda(NatKind, m: NatIdentifier, DepLambda(NatKind, o: NatIdentifier, _))) => (n, m, o)
+ case _ => ???
+ }
+
+ val m: Nat = 1024
+ val n: Nat = 1024
+ val o: Nat = 1024
+ val map = Map(nIdent -> n, mIdent -> m, oIdent -> o)
+
+ val parameters = autotune.constraints.collectParameters(e)
+ val constraints = autotune.constraints.collectConstraints(e, parameters)
+ val constraintsSubstituted = constraints.
+ map(constraint => constraint.substitute(map.asInstanceOf[Map[ArithExpr, ArithExpr]]))
+
+ val dc = distributeConstraints(parameters, constraintsSubstituted)
+
+ var size = 0
+ dc.foreach(elem => {
+ size += elem._2._1.size
+ })
+
+ val tuner = Tuner(
+ hostCode = util.hostcode.convolution(32),
+ samples = 100,
+ name = "RISE",
+ output = "autotuning",
+ timeouts =Timeouts(5000, 5000, 5000),
+ executionIterations = 10,
+ speedupFactor = 100,
+ configFile = None,
+ hmConstraints = false
+ )
+ val json = autotune.configFileGeneration.generateJSON(parameters, constraintsSubstituted, tuner)
+
+ println("json: \n" + json)
+
+ println("gold : \n" + gold)
+
+ assert(util.compareConfigFiles(json, gold))
+
+ }
+}
diff --git a/src/test/scala/rise/autotune/TestConstraints.scala b/src/test/scala/rise/autotune/TestConstraints.scala
new file mode 100644
index 000000000..7f4bad835
--- /dev/null
+++ b/src/test/scala/rise/autotune/TestConstraints.scala
@@ -0,0 +1,138 @@
+package rise.autotune
+
+import arithexpr.arithmetic.{ArithExpr}
+import rise.autotune
+import rise.core.{DepLambda, Expr}
+import rise.core.types.{Nat, NatIdentifier, NatKind, TuningParameter}
+
+class TestConstraints extends test_util.Tests {
+
+ test("collect constraints") {
+ val e: Expr = util.expressions.convolution.convolutionOclGsLsWrap
+ autotune.constraints.collectConstraints(e,
+ autotune.constraints.collectParameters(e))
+ .foreach(println)
+ }
+
+ test("mm kernel constraints") {
+
+ val e: Expr = util.expressions.mm.mmOclGsLsWrap
+
+ val (nIdent, mIdent, oIdent) = e match {
+ case DepLambda(NatKind, n: NatIdentifier, DepLambda(NatKind, m: NatIdentifier, DepLambda(NatKind, o: NatIdentifier, _))) =>
+ (n, m, o)
+ case _ => ???
+ }
+
+ val params = autotune.constraints.collectParameters(e)
+ val constraints = autotune.constraints.collectConstraints(e, params)
+ // note: v5 multiple of 4, contiguous memory constraint is missing
+
+ // n, m, o, v3, v4, v5, v6, v7, v8, ls0, ls1, gs0, gs1
+ val badParameters = Seq[(Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat)](
+ (64, 128, 128, 8, 1, 1, 1, 16, 1, 32, 4, 32, 16),
+ (64, 128, 128, 1, 1, 1, 32, 1, 128, 64, 2, 64, 128),
+ (64, 128, 128, 2, 1, 1, 2, 32, 32, 1, 1, 4, 64),
+ (64, 128, 128, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1),
+ (64, 128, 128, 1, 1, 1, 1, 8, 4, 4, 1, 64, 1),
+ (64, 128, 128, 1, 1, 1, 1, 1, 128, 2, 2, 2, 8),
+ (64, 128, 128, 1, 1, 1, 2, 1, 2, 2, 2, 4, 128),
+ (64, 128, 128, 2, 1, 1, 1, 2, 4, 4, 4, 16, 64),
+ (64, 128, 128, 2, 1, 1, 2, 8, 2, 4, 2, 4, 2),
+ (64, 128, 128, 8, 1, 1, 1, 8, 4, 8, 64, 8, 64),
+ (64, 128, 128, 16, 2, 2, 1, 16, 2, 64, 4, 64, 8),
+ (64, 128, 128, 1, 1, 2, 2, 128, 4, 16, 16, 64, 64),
+ (64, 128, 128, 1, 1, 2, 4, 1, 16, 4, 1, 4, 32),
+ (64, 128, 128, 1, 1, 2, 1, 4, 128, 4, 2, 64, 4),
+ (64, 128, 128, 2, 1, 2, 4, 2, 64, 2, 1, 128, 1),
+ (64, 128, 128, 16, 2, 2, 2, 32, 8, 2, 1, 128, 1),
+ (64, 128, 128, 2, 2, 2, 2, 16, 8, 4, 1, 4, 32),
+ (64, 128, 128, 1, 2, 2, 1, 1, 1, 4, 1, 4, 4),
+ (64, 128, 128, 8, 2, 2, 1, 8, 32, 8, 2, 32, 2),
+ (64, 128, 128, 32, 2, 2, 2, 64, 16, 1, 2, 16, 32),
+ (64, 128, 128, 2, 4, 4, 16, 8, 64, 8, 1, 8, 8),
+ (64, 128, 128, 1, 1, 4, 32, 8, 64, 2, 4, 128, 4),
+ (64, 128, 128, 1, 2, 4, 4, 1, 1, 16, 1, 16, 1),
+ (64, 128, 128, 1, 2, 4, 128, 8, 128, 2, 1, 2, 32),
+ (64, 128, 128, 1, 1, 4, 16, 16, 32, 1, 128, 32, 128),
+ (64, 128, 128, 1, 1, 4, 32, 8, 8, 16, 8, 64, 8),
+ (64, 128, 128, 2, 1, 4, 64, 8, 32, 2, 8, 4, 64),
+ (64, 128, 128, 4, 1, 4, 2, 32, 2, 4, 8, 8, 64),
+ (64, 128, 128, 2, 1, 8, 2, 4, 128, 2, 2, 2, 16),
+ (64, 128, 128, 1, 4, 8, 8, 2, 16, 4, 2, 8, 4),
+ (64, 128, 128, 2, 8, 8, 8, 128, 2, 2, 1, 4, 2),
+ (64, 128, 128, 1, 4, 8, 16, 4, 4, 1, 2, 128, 2),
+ (64, 128, 128, 1, 1, 8, 1, 4, 1, 1, 16, 1, 32),
+ (64, 128, 128, 2, 8, 8, 8, 8, 1, 8, 4, 8, 16),
+ (64, 128, 128, 2, 1, 16, 16, 8, 32, 1, 2, 1, 128),
+ (64, 128, 128, 2, 2, 16, 4, 2, 4, 2, 1, 128, 2),
+ (64, 128, 128, 2, 1, 16, 16, 8, 8, 16, 2, 16, 2),
+ (64, 128, 128, 1, 4, 16, 32, 8, 128, 1, 1, 2, 8),
+ (64, 128, 128, 1, 4, 16, 128, 32, 32, 1, 4, 1, 16),
+ (64, 128, 128, 1, 1, 16, 4, 1, 1, 1, 4, 32, 32),
+ (64, 128, 128, 2, 1, 32, 1, 4, 8, 8, 2, 128, 2),
+ (64, 128, 128, 1, 4, 32, 1, 4, 64, 1, 8, 1, 8),
+ (64, 128, 128, 1, 1, 32, 2, 1, 8, 8, 1, 64, 1),
+ (64, 128, 128, 1, 8, 32, 32, 1, 64, 1, 1, 1, 64),
+ (64, 128, 128, 1, 32, 32, 16, 64, 32, 1, 1, 8, 16),
+ (64, 128, 128, 2, 32, 32, 4, 4, 2, 16, 8, 32, 64),
+ (64, 128, 128, 32, 8, 32, 2, 32, 1, 2, 8, 2, 8),
+ (64, 128, 128, 2, 8, 64, 4, 4, 64, 1, 8, 1, 32),
+ (64, 128, 128, 2, 1, 64, 16, 2, 4, 1, 1, 4, 64),
+ (64, 128, 128, 1, 4, 64, 8, 1, 128, 1, 2, 16, 4),
+ (64, 128, 128, 2, 16, 64, 2, 2, 8, 2, 2, 2, 2),
+ (64, 128, 128, 1, 8, 64, 1, 1, 1, 1, 1, 1, 2),
+ (64, 128, 128, 1, 1, 64, 1, 2, 8, 32, 64, 64, 128),
+ (64, 128, 128, 1, 64, 64, 64, 1, 4, 1, 2, 1, 16),
+ (64, 128, 128, 2, 64, 64, 4, 2, 1, 2, 8, 2, 32),
+ (64, 128, 128, 64, 32, 64, 1, 64, 64, 32, 1, 128, 64),
+ (64, 128, 128, 32, 32, 128, 1, 64, 4, 64, 1, 64, 1),
+ (64, 128, 128, 4, 2, 128, 32, 4, 8, 1, 1, 8, 4),
+ (64, 128, 128, 4, 128, 128, 1, 4, 32, 2, 16, 2, 64),
+ (64, 128, 128, 1, 8, 128, 128, 1, 32, 2, 2, 4, 16),
+ (64, 128, 128, 1, 32, 128, 2, 1, 128, 4, 1, 64, 8),
+ (64, 128, 128, 1, 8, 128, 8, 4, 128, 4, 8, 8, 16),
+ (64, 128, 128, 8, 128, 128, 128, 16, 16, 8, 64, 16, 64),
+ (64, 128, 128, 16, 64, 128, 1, 128, 128, 1, 2, 1, 4),
+ (64, 128, 128, 16, 128, 128, 8, 32, 8, 1, 2, 1, 2),
+ (64, 128, 128, 2, 1, 1, 8, 4, 16, 2, 2, 2, 2),
+ )
+ val goodParameters = Seq[(Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat)](
+ (64, 128, 128, 4, 1, 1, 4, 4, 8, 8, 4, 8, 32),
+ (64, 128, 128, 4, 1, 1, 8, 64, 16, 1, 16, 4, 32),
+ (64, 128, 128, 4, 1, 1, 8, 128, 64, 1, 8, 8, 8),
+ (64, 128, 128, 4, 1, 2, 4, 64, 128, 4, 2, 4, 4),
+ (64, 128, 128, 64, 2, 2, 32, 64, 32, 1, 1, 2, 32),
+ (64, 128, 128, 4, 1, 2, 8, 8, 64, 32, 2, 32, 16),
+ (64, 128, 128, 4, 1, 2, 32, 4, 32, 4, 4, 4, 4),
+ )
+ for ((params, isGood) <- Seq((badParameters, false), (goodParameters, true))) {
+ params.foreach { case cfg@(n, m, o, v3, v4, v5, v6, v7, v8, ls0, ls1, gs0, gs1) =>
+ val map = Map(
+ nIdent -> n,
+ mIdent -> m,
+ oIdent -> o,
+ TuningParameter("v3") -> v3,
+ TuningParameter("v4") -> v4,
+ TuningParameter("v5") -> v5,
+ TuningParameter("v6") -> v6,
+ TuningParameter("v7") -> v7,
+ TuningParameter("v8") -> v8,
+ TuningParameter("ls0") -> ls0,
+ TuningParameter("ls1") -> ls1,
+ TuningParameter("gs0") -> gs0,
+ TuningParameter("gs1") -> gs1,
+ )
+ if (autotune.constraints.checkConstraints(constraints, map) != isGood) {
+ val (sat, notSat) = constraints.partition(c =>
+ c.substitute(map.toMap[ArithExpr, ArithExpr]).isSatisfied())
+ println("satisfied:")
+ sat.foreach(println)
+ println("not satisfied:")
+ notSat.foreach(println)
+ throw new Exception(s"$cfg should${if (isGood) "" else " not"} pass constraint checking")
+ }
+ }
+ }
+ }
+}
diff --git a/src/test/scala/rise/autotune/TestExecution.scala b/src/test/scala/rise/autotune/TestExecution.scala
new file mode 100644
index 000000000..27db23b73
--- /dev/null
+++ b/src/test/scala/rise/autotune/TestExecution.scala
@@ -0,0 +1,295 @@
+package rise.autotune
+
+import rise.autotune
+import rise.core.Expr
+import rise.core.types.{Nat, TuningParameter}
+
+class TestExecution extends test_util.Tests {
+
+ def executeConfig(e: Expr, params: Map[Nat, Nat], hostCode: HostCode): ExecutionResult = {
+
+ val eReplaced = rise.core.substitute.natsInExpr(params, e)
+
+ val result = autotune.execution.execute(
+ expression = eReplaced,
+ hostCode = hostCode,
+ timeouts = Timeouts(5000, 5000, 5000),
+ executionIterations = 100,
+ speedupFactor = 100,
+ execution = Median
+ )
+
+ result
+ }
+
+ test("execute convolution") {
+ val goodParameters: Map[Nat, Nat] = Map(
+ TuningParameter("vec") -> (4: Nat),
+ TuningParameter("tile") -> (16: Nat)
+ )
+
+ val e: Expr = util.expressions.convolution.convolutionOcl
+ val e2 = rise.core.substitute.natsInExpr(goodParameters, e)
+
+ val result = autotune.execution.execute(
+ expression = e2,
+ hostCode = util.hostcode.convolution(32),
+ timeouts = Timeouts(5000, 5000, 5000),
+ executionIterations = 10,
+ speedupFactor = 100,
+ execution = Median)
+
+ // check if result has valid runtime
+ assert(result.runtime.isRight)
+ println("result: " + result)
+
+ // try to execute with zero execution iterations
+ assertThrows[java.lang.AssertionError] {
+ autotune.execution.execute(
+ expression = e2,
+ hostCode = util.hostcode.convolution(32),
+ timeouts = Timeouts(5000, 5000, 5000),
+ executionIterations = 0,
+ speedupFactor = 100,
+ execution = Median)
+ }
+ }
+
+ test("execute scal") {
+ val e: Expr = util.expressions.scal.scalOcl(1024)
+
+ val result = autotune.execution.execute(
+ expression = e,
+ hostCode = util.hostcode.scal(1024),
+ timeouts = Timeouts(5000, 5000, 5000),
+ executionIterations = 10,
+ speedupFactor = 100,
+ execution = Minimum)
+
+ // check if result has valid runtime
+ assert(result.runtime.isRight)
+ println("result: \n" + result)
+ }
+
+ test("execute mm"){
+ val mm: Expr = util.expressions.mm.mmOclGsLsWrap
+
+ val params0:Map[Nat, Nat] = Map(
+ TuningParameter("ls0") -> (16: Nat),
+ TuningParameter("ls1") -> (16: Nat),
+ TuningParameter("gs0") -> (1024: Nat),
+ TuningParameter("gs1") -> (256: Nat),
+ TuningParameter("v3") -> (4: Nat),
+ TuningParameter("v4") -> (1: Nat),
+ TuningParameter("v5") -> (4: Nat),
+ TuningParameter("v6") -> (64: Nat),
+ TuningParameter("v7") -> (256: Nat),
+ TuningParameter("v8") -> (32: Nat)
+ )
+
+ val params1:Map[Nat, Nat] = Map(
+ TuningParameter("ls0") -> (8: Nat),
+ TuningParameter("ls1") -> (4: Nat),
+ TuningParameter("gs0") -> (1024: Nat),
+ TuningParameter("gs1") -> (32: Nat),
+ TuningParameter("v3") -> (4: Nat),
+ TuningParameter("v4") -> (8: Nat),
+ TuningParameter("v5") -> (32: Nat),
+ TuningParameter("v6") -> (64: Nat),
+ TuningParameter("v7") -> (32: Nat),
+ TuningParameter("v8") -> (128: Nat)
+ )
+
+ val paramSet = Set(params0, params1)
+
+ paramSet.foreach(params => {
+
+ val result = executeConfig(mm, params, util.hostcode.mm(1024, 1024, 1024))
+
+ println("result: " + result.runtime)
+
+ // check for execution error
+ result.runtime match {
+ case Left(value) => value.errorLevel.equals(EXECUTION_ERROR)
+ case Right(_) => // do nothing result is fine
+ }
+ })
+ }
+
+ test("generate huge amount of code") {
+ // expression
+ val e: Expr = util.expressions.convolution.convolutionOclGsLs(1024)
+
+ // define parameters to break the code-gen
+ val parameters: Map[Nat, Nat] = Map(
+ TuningParameter("vec") -> (16: Nat),
+ TuningParameter("tile") -> (32: Nat),
+ TuningParameter("gs0") -> (1: Nat),
+ TuningParameter("gs1") -> (512: Nat),
+ TuningParameter("ls0") -> (1: Nat),
+ TuningParameter("ls1") -> (64: Nat)
+ )
+
+ // substitute parameters
+ val eWithParams = rise.core.substitute.natsInExpr(parameters, e)
+
+ println("run codegen with timeout ")
+ // WARNING: timeout does not stop the thread, it only returns to the host thread
+ val result = autotune.execution.execute(
+ eWithParams,
+ util.hostcode.convolution(1024),
+ Timeouts(5000, 5000, 5000),
+ 10,
+ 100,
+ execution = Median
+ )
+
+ print("result: " + result)
+
+ result.runtime match {
+ case Right(_) => assert(false)
+ case Left(error) => assert(error.errorLevel.equals(autotune.CODE_GENERATION_ERROR))
+ }
+ }
+
+ test("test xml parsing") {
+
+ // scalastyle:off
+ val xmlString =
+ """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ // scalastyle:on
+ assert(autotune.execution.getRuntimeFromClap(xmlString)(0).value.toFloat == 0.010112f)
+ }
+
+ test("text xml parsing with corrupted xml string") {
+ // scalastyle:off
+ val corruptedXmlString =
+ """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ // scalastyle:on
+ assert(autotune.execution.getRuntimeFromClap(corruptedXmlString)(0).value.toFloat == 0.158819f)
+ }
+
+ test("test xml parsing for multiple runtimes"){
+ // scalastyle:off
+ val xmlString =
+ """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+
+ // scalastyle:on
+
+ val gold = Seq(
+ 4.126528,
+ 4.286464,
+ 3.551232,
+ 3.549504,
+ 3.551104,
+ 4.312768,
+ 3.552096,
+ 4.13136,
+ 4.25408,
+ 4.302944
+ )
+
+ val runtimes = autotune.execution.getRuntimeFromClap(xmlString)
+
+ assert(runtimes.map(elem => elem.value) == gold)
+ }
+}
diff --git a/src/test/scala/rise/autotune/util/package.scala b/src/test/scala/rise/autotune/util/package.scala
new file mode 100644
index 000000000..17c085fba
--- /dev/null
+++ b/src/test/scala/rise/autotune/util/package.scala
@@ -0,0 +1,262 @@
+package rise.autotune
+
+import apps.mm.mmNVIDIAWithParams
+import apps.separableConvolution2D.weightsSeqVecUnroll
+import arithexpr.arithmetic._
+import rise.core.DSL.HighLevelConstructs.{slideVectors, tileShiftInwards}
+import rise.core.DSL.Type._
+import rise.core.DSL._
+import rise.core._
+import rise.core.primitives.{let => _, _}
+import rise.core.types.DataType._
+import rise.core.types.{NatIdentifier, _}
+import rise.openCL.DSL._
+import shine.OpenCL.{GlobalSize, LocalSize}
+import play.api.libs.json.Json
+
+package object util {
+
+ def compareConfigFiles(file: String, gold: String): Boolean = {
+ Json.parse(file).equals(Json.parse(gold))
+ }
+
+ object expressions {
+
+ object convolution {
+
+ val convolution: ToBeTyped[Expr] =
+ // tileShiftInwards should constrain n >= tile
+ // slideVectors and slide should constrain tile % vec = 0
+ tuningParam("vec", RangeAdd(1, 32, 1), (vec: Nat) =>
+ tuningParam("tile", RangeAdd(4, 32, 1), (tile: Nat) =>
+ depFun(RangeAdd(1, PosInf, vec), (n: Nat) =>
+ fun(3 `.` f32)(weights =>
+ fun(((n + 2) `.` f32) ->: (n `.` f32))(input =>
+ input |> tileShiftInwards(tile)(mapWorkGroup(0)(
+ slideVectors(vec) >> slide(3)(vec) >>
+ mapLocal(0)(weightsSeqVecUnroll(weights)) >>
+ asScalar
+ ))
+ )))))
+
+ val convolutionOcl: ToBeTyped[Expr] =
+ // tileShiftInwards should constrain n >= tile
+ // slideVectors and slide should constrain tile % vec = 0
+ tuningParam("vec", RangeAdd(1, 32, 1), (vec: Nat) =>
+ tuningParam("tile", RangeAdd(4, 32, 1), (tile: Nat) =>
+ depFun(RangeAdd(1, PosInf, vec), (n: Nat) =>
+ fun(3 `.` f32)(weights =>
+ fun(((n + 2) `.` f32) ->: (n `.` f32))(input =>
+ oclRun(LocalSize(1), GlobalSize(32))(
+ input |> tileShiftInwards(tile)(mapWorkGroup(0)(
+ slideVectors(vec) >> slide(3)(vec) >>
+ mapLocal(0)(weightsSeqVecUnroll(weights)) >>
+ asScalar
+ ))
+ ))))))
+
+ val convolutionOclGsLsWrap: Expr =
+ tuningParam("ls0", (ls0: Nat) => tuningParam("ls1", (ls1: Nat) =>
+ tuningParam("gs0", (gs0: Nat) => tuningParam("gs1", (gs1: Nat) =>
+ wrapOclRun(LocalSize(ls0, ls1), GlobalSize(gs0, gs1))(convolution)
+ ))))
+
+ val convolutionOclGsLs: ToBeTyped[Expr] = {
+ // tileShiftInwards should constrain n >= tile
+ // slideVectors and slide should constrain tile % vec = 0
+ tuningParam("ls0", RangeMul(1, 1024, 2), (ls0: Nat) =>
+ tuningParam("ls1", RangeMul(1, 1024, 2), (ls1: Nat) =>
+ tuningParam("gs0", RangeMul(1, 1024, 2), (gs0: Nat) =>
+ tuningParam("gs1", RangeMul(1, 1024, 2), (gs1: Nat) =>
+ tuningParam("vec", RangeAdd(1, 32, 1), (vec: Nat) =>
+ tuningParam("tile", RangeAdd(4, 1024, 1), (tile: Nat) =>
+ depFun(RangeAdd(1, PosInf, vec), (n: Nat) =>
+ fun(3 `.` f32)(weights =>
+ fun(((n + 2) `.` f32) ->: (n `.` f32))(input =>
+ oclRun(LocalSize(ls0, ls1), GlobalSize(gs0, gs1))(
+ input |> tileShiftInwards(tile)(mapWorkGroup(0)(
+ slideVectors(vec) >> slide(3)(vec) >>
+ mapLocal(0)(weightsSeqVecUnroll(weights)) >>
+ asScalar
+ ))
+ ))))))))))
+ }
+ }
+
+ object scal {
+
+ val scalSJ: ToBeTyped[Expr] =
+ depFun((n: Nat) => fun(n `.` f32)(input => fun(f32)(alpha =>
+ oclRun(LocalSize(1), GlobalSize(32))(
+ input |> split(4) |> mapGlobal(0)(fun(x => alpha * x)) |> join)
+ )))
+
+ val scalOcl: ToBeTyped[Expr] =
+ depFun((n: Nat) => fun(n `.` f32)(input => fun(f32)(alpha =>
+ oclRun(LocalSize(1), GlobalSize(32))(
+ input |> mapGlobal(0)(fun(x => alpha * x)))
+ )))
+
+ val scal: ToBeTyped[Expr] =
+ depFun((n: Nat) => fun(n `.` f32)(input => fun(f32)(alpha =>
+ input |> mapGlobal(0)(fun(x => alpha * x)))
+ ))
+ }
+
+ object mm {
+
+ val mmKernel: ToBeTyped[Expr] =
+ tuningParam("v3", RangeAdd(1,1024,1), (v3: Nat) =>
+ tuningParam("v4", RangeAdd(1,1024,1), (v4: Nat) =>
+ tuningParam("v5", RangeAdd(1,1024,1), (v5: Nat) =>
+ tuningParam("v6", RangeAdd(1,1024,1), (v6: Nat) =>
+ tuningParam("v7", RangeAdd(1,1024,1), (v7: Nat) =>
+ tuningParam("v8", RangeAdd(1,1024,1), (v8: Nat) =>
+ mmNVIDIAWithParams(v3, v4, v5, v6, v7, v8)
+ ))))))
+
+ val mmOclGsLsWrap: ToBeTyped[Expr] =
+ tuningParam("ls0", (ls0: Nat) =>
+ tuningParam("ls1", (ls1: Nat) =>
+ tuningParam("gs0", (gs0: Nat) =>
+ tuningParam("gs1", (gs1: Nat) =>
+ wrapOclRun(LocalSize(ls0, ls1), GlobalSize(gs0, gs1))(mmKernel)
+ ))))
+
+ val mmOclGsLsWrapRanges: ToBeTyped[Expr] =
+ tuningParam("ls0", RangeAdd(1, 1024, 1), (ls0: Nat) =>
+ tuningParam("ls1", RangeAdd(1, 1024, 1), (ls1: Nat) =>
+ tuningParam("gs0", RangeAdd(1, 1024, 1), (gs0: Nat) =>
+ tuningParam("gs1", RangeAdd(1, 1024, 1), (gs1: Nat) =>
+ wrapOclRun(LocalSize(ls0, ls1), GlobalSize(gs0, gs1))(mmKernel)
+ ))))
+ }
+ }
+
+ object hostcode {
+
+ val convolution: Int => HostCode = N => {
+
+ // scalastyle:off
+ val init: Int => String = (N) => {
+ s"""
+ |const int N = ${N};
+ |
+ |Buffer input = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_READ);
+ |Buffer output = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_WRITE);
+ |
+ |float* in = hostBufferSync(ctx, input, N * sizeof(float), HOST_WRITE);
+ |for (int i = 0; i < N; i++) {
+ | in[i] = 1;
+ |}
+ |
+ |""".stripMargin
+ }
+
+ val compute =
+ s"""
+ |fun_run(ctx, &fun, output, N, input, input);
+ |""".stripMargin
+
+ val finish =
+ s"""
+ |// TODO: could check output here
+ |
+ |destroyBuffer(ctx, input);
+ |destroyBuffer(ctx, output);
+ |""".stripMargin
+ // scalastyle:on
+
+ HostCode(init(N), compute, finish)
+ }
+
+ val scal: Int => HostCode = N => {
+
+ // scalastyle:off
+ val init: Int => String = (N) => {
+ s"""
+ |const int N = ${N};
+ |
+ |Buffer input = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_READ);
+ |Buffer output = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_WRITE);
+ |
+ |float* in = hostBufferSync(ctx, input, N * sizeof(float), HOST_WRITE);
+ |for (int i = 0; i < N; i++) {
+ | in[i] = 1;
+ |}
+ |
+ |// synchronize before entering timed section
+ |deviceBufferSync(ctx, input, N * sizeof(float), DEVICE_READ);
+ |
+ |""".stripMargin
+ }
+
+ val compute =
+ s"""
+ |fun_run(ctx, &fun, output, input, 4);
+ |""".stripMargin
+
+ val finish =
+ s"""
+ | float* out = hostBufferSync(ctx, output, N * sizeof(float), HOST_READ);
+ | for (int i = 0; i < N; i++) {
+ | if (out[i] != 4) {
+ | exit(EXIT_FAILURE);
+ | }
+ | }
+ |
+ |destroyBuffer(ctx, input);
+ |destroyBuffer(ctx, output);
+ |""".stripMargin
+ // scalastyle:on
+
+ HostCode(init(N), compute, finish)
+ }
+
+ val mm: (Int, Int, Int) => HostCode = (N, M, O) => {
+
+ // scalastyle:off
+ val init: (Int, Int, Int) => String = (N, M, O) => {
+ s"""
+ |const int N = ${N};
+ |const int M = ${M};
+ |const int O = ${O};
+ |
+ |srand(time(NULL));
+ |
+ |Buffer inputA = createBuffer(ctx, N * M * sizeof(float), HOST_WRITE | DEVICE_READ);
+ |Buffer inputB = createBuffer(ctx, M * O * sizeof(float), HOST_WRITE | DEVICE_READ);
+ |Buffer outputC = createBuffer(ctx, N * O * sizeof(float), HOST_READ | DEVICE_WRITE);
+ |
+ |float* inA = hostBufferSync(ctx, inputA, N * M * sizeof(float), HOST_WRITE);
+ |for (int i = 0; i < N * M ; i++) {
+ | inA[i] = (float)(rand());
+ |}
+ |
+ |float* inB = hostBufferSync(ctx, inputB, M * O * sizeof(float), HOST_WRITE);
+ |for (int i = 0; i < M * O; i++) {
+ | inB[i] = (float)(rand());
+ |}
+ |
+ |""".stripMargin
+ }
+
+ val compute =
+ s"""
+ |fun_run(ctx, &fun, outputC, M, N, O, inputA, inputB);
+ |""".stripMargin
+
+ val finish =
+ s"""
+ |// TODO: could check output here
+ |
+ |destroyBuffer(ctx, inputA);
+ |destroyBuffer(ctx, inputB);
+ |destroyBuffer(ctx, outputC);
+ |""".stripMargin
+ // scalastyle:on
+
+ HostCode(init(N, M, O), compute, finish)
+ }
+ }
+}
diff --git a/src/test/scala/rise/autotuning.scala b/src/test/scala/rise/autotuning.scala
deleted file mode 100644
index 5406c6df8..000000000
--- a/src/test/scala/rise/autotuning.scala
+++ /dev/null
@@ -1,643 +0,0 @@
-package rise
-
-import apps.mm.mmNVIDIAWithParams
-import arithexpr.arithmetic.{ArithExpr, PosInf, RangeAdd, RangeMul, RangeUnknown}
-import rise.core._
-import rise.core.types.{NatIdentifier, _}
-import rise.core.types.DataType._
-import rise.core.primitives.{let => _, _}
-import rise.core.DSL._
-import rise.core.DSL.Type._
-import rise.core.DSL.HighLevelConstructs.{slideVectors, tileShiftInwards}
-import rise.openCL.DSL._
-import apps.separableConvolution2D.weightsSeqVecUnroll
-import shine.OpenCL.{GlobalSize, LocalSize}
-import rise.autotune._
-import rise.autotune.configFileGeneration.{check_no_cycle}
-
-
-class autotuning extends test_util.Tests {
- val convolution: ToBeTyped[Expr] =
- // tileShiftInwards should constrain n >= tile
- // slideVectors and slide should constrain tile % vec = 0
- tuningParam("vec", RangeAdd(1, 32, 1), (vec: Nat) =>
- tuningParam("tile", RangeAdd(4, 32, 1), (tile: Nat) =>
- depFun(RangeAdd(1, PosInf, vec), (n: Nat) =>
- fun(3 `.` f32)(weights =>
- fun(((n + 2) `.` f32) ->: (n `.` f32))(input =>
- input |> tileShiftInwards(tile)(mapWorkGroup(0)(
- slideVectors(vec) >> slide(3)(vec) >>
- mapLocal(0)(weightsSeqVecUnroll(weights)) >>
- asScalar
- ))
- )))))
-
- val convolutionOcl: ToBeTyped[Expr] =
- // tileShiftInwards should constrain n >= tile
- // slideVectors and slide should constrain tile % vec = 0
- tuningParam("vec", RangeAdd(1, 32, 1), (vec: Nat) =>
- tuningParam("tile", RangeAdd(4, 32, 1), (tile: Nat) =>
- depFun(RangeAdd(1, PosInf, vec), (n: Nat) =>
- fun(3 `.` f32)(weights =>
- fun(((n + 2) `.` f32) ->: (n `.` f32))(input =>
- oclRun(LocalSize(1), GlobalSize(32))(
- input |> tileShiftInwards(tile)(mapWorkGroup(0)(
- slideVectors(vec) >> slide(3)(vec) >>
- mapLocal(0)(weightsSeqVecUnroll(weights)) >>
- asScalar
- ))
- ))))))
-
- val convolutionOclGsLsWrap: Expr =
- tuningParam("ls0", (ls0: Nat) => tuningParam("ls1", (ls1: Nat) =>
- tuningParam("gs0", (gs0: Nat) => tuningParam("gs1", (gs1: Nat) =>
- wrapOclRun(LocalSize(ls0, ls1), GlobalSize(gs0, gs1))(convolution)
- ))))
-
- val convolutionOclGsLs: ToBeTyped[Expr] = {
- // tileShiftInwards should constrain n >= tile
- // slideVectors and slide should constrain tile % vec = 0
- tuningParam("ls0", RangeMul(1, 1024, 2), (ls0: Nat) =>
- tuningParam("ls1", RangeMul(1, 1024, 2), (ls1: Nat) =>
- tuningParam("gs0", RangeMul(1, 1024, 2), (gs0: Nat) =>
- tuningParam("gs1", RangeMul(1, 1024, 2), (gs1: Nat) =>
- tuningParam("vec", RangeAdd(1, 32, 1), (vec: Nat) =>
- tuningParam("tile", RangeAdd(4, 1024, 1), (tile: Nat) =>
- depFun(RangeAdd(1, PosInf, vec), (n: Nat) =>
- fun(3 `.` f32)(weights =>
- fun(((n + 2) `.` f32) ->: (n `.` f32))(input =>
- oclRun(LocalSize(ls0, ls1), GlobalSize(gs0, gs1))(
- input |> tileShiftInwards(tile)(mapWorkGroup(0)(
- slideVectors(vec) >> slide(3)(vec) >>
- mapLocal(0)(weightsSeqVecUnroll(weights)) >>
- asScalar
- ))
- ))))))))))
- }
-
- val scalSJ: ToBeTyped[Expr] =
- depFun((n: Nat) => fun(n `.` f32)(input => fun(f32)(alpha =>
- oclRun(LocalSize(1), GlobalSize(32))(
- input |> split(4) |> mapGlobal(0)(fun(x => alpha * x)) |> join)
- )))
-
- val scalOcl: ToBeTyped[Expr] =
- depFun((n: Nat) => fun(n `.` f32)(input => fun(f32)(alpha =>
- oclRun(LocalSize(1), GlobalSize(32))(
- input |> mapGlobal(0)(fun(x => alpha * x)))
- )))
-
- val scal: ToBeTyped[Expr] =
- depFun((n: Nat) => fun(n `.` f32)(input => fun(f32)(alpha =>
- input |> mapGlobal(0)(fun(x => alpha * x)))
- ))
-
- // scalastyle:off
- val main: Int => String = iterations => {
- s"""
- const int N = ${iterations};
- int main(int argc, char** argv) {
- Context ctx = createDefaultContext();
- Buffer input = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_READ);
- Buffer output = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_WRITE);
-
- float* in = hostBufferSync(ctx, input, N * sizeof(float), HOST_WRITE);
- for (int i = 0; i < N; i++) {
- in[i] = 1;
- }
-
- foo_init_run(ctx, output, input, input);
-
- float* out = hostBufferSync(ctx, output, N * sizeof(float), HOST_READ);
-
-// todo add error checking
-
- destroyBuffer(ctx, input);
- destroyBuffer(ctx, output);
- destroyContext(ctx);
- return EXIT_SUCCESS;
- }
- """
- }
- // scalastyle:on
-
-
-
-
- test("collect parameters") {
- val params = autotune.constraints.collectParameters(convolutionOclGsLsWrap)
- assert(params.find(IsTuningParameter("vec")).get.range == RangeAdd(1, 32, 1))
- assert(params.find(IsTuningParameter("tile")).get.range == RangeAdd(4, 32, 1))
- assert(params.find(IsTuningParameter("ls0")).get.range == RangeUnknown)
- assert(params.find(IsTuningParameter("ls1")).get.range == RangeUnknown)
- assert(params.find(IsTuningParameter("gs0")).get.range == RangeUnknown)
- assert(params.find(IsTuningParameter("gs1")).get.range == RangeUnknown)
- assert(params.size == 6)
- }
-
- test("collect constraints") {
- val e: Expr = convolutionOclGsLsWrap
- autotune.constraints.collectConstraints(e,
- autotune.constraints.collectParameters(e))
- .foreach(println)
- }
-
- test("substitute parameters") {
- val e: Expr = convolution(32)
- val constraints = autotune.constraints.collectConstraints(e,
- autotune.constraints.collectParameters(e))
- println("constraints: \n" + constraints)
-
- val badParameters1 = Map(
- TuningParameter("vec") -> (5: Nat),
- TuningParameter("tile") -> (15: Nat)
- )
- assert(!autotune.constraints.checkConstraints(constraints, badParameters1))
-
- val badParameters2 = Map(
- TuningParameter("vec") -> (4: Nat),
- TuningParameter("tile") -> (13: Nat)
- )
- assert(!autotune.constraints.checkConstraints(constraints, badParameters2))
-
- /* FIXME: there is no `n >= tile` constraint collected
- val badParameters3 = Map(
- TuningParameter("vec") -> (8: Nat),
- TuningParameter("tile") -> (64: Nat)
- )
- assert(!autotune.checkConstraints(constraints, badParameters3))
- */
-
- val goodParameters = Map(
- TuningParameter("vec") -> (4: Nat),
- TuningParameter("tile") -> (16: Nat)
- )
- assert(autotune.constraints.checkConstraints(constraints, goodParameters))
- rise.core.substitute.natsInExpr(goodParameters.toMap[Nat, Nat], e)
- }
-
- val mmKernel: ToBeTyped[Expr] =
- tuningParam("v3", (v3: Nat) =>
- tuningParam("v4", (v4: Nat) =>
- tuningParam("v5", (v5: Nat) =>
- tuningParam("v6", (v6: Nat) =>
- tuningParam("v7", (v7: Nat) =>
- tuningParam("v8", (v8: Nat) =>
- mmNVIDIAWithParams(v3, v4, v5, v6, v7, v8)
- ))))))
-
- test("mm kernel constraints") {
- val e: Expr =
- tuningParam("ls0", (ls0: Nat) => tuningParam("ls1", (ls1: Nat) =>
- tuningParam("gs0", (gs0: Nat) => tuningParam("gs1", (gs1: Nat) =>
- wrapOclRun(LocalSize(ls0, ls1), GlobalSize(gs0, gs1))(mmKernel)
- ))))
- val (nIdent, mIdent, oIdent) = e match {
- case DepLambda(NatKind,
- n: NatIdentifier,
- DepLambda(NatKind, m: NatIdentifier, DepLambda(NatKind, o: NatIdentifier, _))) =>
- (n, m, o)
- case _ => ???
- }
-
- val params = autotune.constraints.collectParameters(e)
- val constraints = autotune.constraints.collectConstraints(e, params)
- // note: v5 multiple of 4, contiguous memory constraint is missing
-
- // n, m, o, v3, v4, v5, v6, v7, v8, ls0, ls1, gs0, gs1
- val badParameters = Seq[(Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat)](
- (64, 128, 128, 8, 1, 1, 1, 16, 1, 32, 4, 32, 16),
- (64, 128, 128, 1, 1, 1, 32, 1, 128, 64, 2, 64, 128),
- (64, 128, 128, 2, 1, 1, 2, 32, 32, 1, 1, 4, 64),
- (64, 128, 128, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1),
- (64, 128, 128, 1, 1, 1, 1, 8, 4, 4, 1, 64, 1),
- (64, 128, 128, 1, 1, 1, 1, 1, 128, 2, 2, 2, 8),
- (64, 128, 128, 1, 1, 1, 2, 1, 2, 2, 2, 4, 128),
- (64, 128, 128, 2, 1, 1, 1, 2, 4, 4, 4, 16, 64),
- (64, 128, 128, 2, 1, 1, 2, 8, 2, 4, 2, 4, 2),
- (64, 128, 128, 8, 1, 1, 1, 8, 4, 8, 64, 8, 64),
- (64, 128, 128, 16, 2, 2, 1, 16, 2, 64, 4, 64, 8),
- (64, 128, 128, 1, 1, 2, 2, 128, 4, 16, 16, 64, 64),
- (64, 128, 128, 1, 1, 2, 4, 1, 16, 4, 1, 4, 32),
- (64, 128, 128, 1, 1, 2, 1, 4, 128, 4, 2, 64, 4),
- (64, 128, 128, 2, 1, 2, 4, 2, 64, 2, 1, 128, 1),
- (64, 128, 128, 16, 2, 2, 2, 32, 8, 2, 1, 128, 1),
- (64, 128, 128, 2, 2, 2, 2, 16, 8, 4, 1, 4, 32),
- (64, 128, 128, 1, 2, 2, 1, 1, 1, 4, 1, 4, 4),
- (64, 128, 128, 8, 2, 2, 1, 8, 32, 8, 2, 32, 2),
- (64, 128, 128, 32, 2, 2, 2, 64, 16, 1, 2, 16, 32),
- (64, 128, 128, 2, 4, 4, 16, 8, 64, 8, 1, 8, 8),
- (64, 128, 128, 1, 1, 4, 32, 8, 64, 2, 4, 128, 4),
- (64, 128, 128, 1, 2, 4, 4, 1, 1, 16, 1, 16, 1),
- (64, 128, 128, 1, 2, 4, 128, 8, 128, 2, 1, 2, 32),
- (64, 128, 128, 1, 1, 4, 16, 16, 32, 1, 128, 32, 128),
- (64, 128, 128, 1, 1, 4, 32, 8, 8, 16, 8, 64, 8),
- (64, 128, 128, 2, 1, 4, 64, 8, 32, 2, 8, 4, 64),
- (64, 128, 128, 4, 1, 4, 2, 32, 2, 4, 8, 8, 64),
- (64, 128, 128, 2, 1, 8, 2, 4, 128, 2, 2, 2, 16),
- (64, 128, 128, 1, 4, 8, 8, 2, 16, 4, 2, 8, 4),
- (64, 128, 128, 2, 8, 8, 8, 128, 2, 2, 1, 4, 2),
- (64, 128, 128, 1, 4, 8, 16, 4, 4, 1, 2, 128, 2),
- (64, 128, 128, 1, 1, 8, 1, 4, 1, 1, 16, 1, 32),
- (64, 128, 128, 2, 8, 8, 8, 8, 1, 8, 4, 8, 16),
- (64, 128, 128, 2, 1, 16, 16, 8, 32, 1, 2, 1, 128),
- (64, 128, 128, 2, 2, 16, 4, 2, 4, 2, 1, 128, 2),
- (64, 128, 128, 2, 1, 16, 16, 8, 8, 16, 2, 16, 2),
- (64, 128, 128, 1, 4, 16, 32, 8, 128, 1, 1, 2, 8),
- (64, 128, 128, 1, 4, 16, 128, 32, 32, 1, 4, 1, 16),
- (64, 128, 128, 1, 1, 16, 4, 1, 1, 1, 4, 32, 32),
- (64, 128, 128, 2, 1, 32, 1, 4, 8, 8, 2, 128, 2),
- (64, 128, 128, 1, 4, 32, 1, 4, 64, 1, 8, 1, 8),
- (64, 128, 128, 1, 1, 32, 2, 1, 8, 8, 1, 64, 1),
- (64, 128, 128, 1, 8, 32, 32, 1, 64, 1, 1, 1, 64),
- (64, 128, 128, 1, 32, 32, 16, 64, 32, 1, 1, 8, 16),
- (64, 128, 128, 2, 32, 32, 4, 4, 2, 16, 8, 32, 64),
- (64, 128, 128, 32, 8, 32, 2, 32, 1, 2, 8, 2, 8),
- (64, 128, 128, 2, 8, 64, 4, 4, 64, 1, 8, 1, 32),
- (64, 128, 128, 2, 1, 64, 16, 2, 4, 1, 1, 4, 64),
- (64, 128, 128, 1, 4, 64, 8, 1, 128, 1, 2, 16, 4),
- (64, 128, 128, 2, 16, 64, 2, 2, 8, 2, 2, 2, 2),
- (64, 128, 128, 1, 8, 64, 1, 1, 1, 1, 1, 1, 2),
- (64, 128, 128, 1, 1, 64, 1, 2, 8, 32, 64, 64, 128),
- (64, 128, 128, 1, 64, 64, 64, 1, 4, 1, 2, 1, 16),
- (64, 128, 128, 2, 64, 64, 4, 2, 1, 2, 8, 2, 32),
- (64, 128, 128, 64, 32, 64, 1, 64, 64, 32, 1, 128, 64),
- (64, 128, 128, 32, 32, 128, 1, 64, 4, 64, 1, 64, 1),
- (64, 128, 128, 4, 2, 128, 32, 4, 8, 1, 1, 8, 4),
- (64, 128, 128, 4, 128, 128, 1, 4, 32, 2, 16, 2, 64),
- (64, 128, 128, 1, 8, 128, 128, 1, 32, 2, 2, 4, 16),
- (64, 128, 128, 1, 32, 128, 2, 1, 128, 4, 1, 64, 8),
- (64, 128, 128, 1, 8, 128, 8, 4, 128, 4, 8, 8, 16),
- (64, 128, 128, 8, 128, 128, 128, 16, 16, 8, 64, 16, 64),
- (64, 128, 128, 16, 64, 128, 1, 128, 128, 1, 2, 1, 4),
- (64, 128, 128, 16, 128, 128, 8, 32, 8, 1, 2, 1, 2),
- (64, 128, 128, 2, 1, 1, 8, 4, 16, 2, 2, 2, 2),
- )
- val goodParameters = Seq[(Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat)](
- (64, 128, 128, 4, 1, 1, 4, 4, 8, 8, 4, 8, 32),
- (64, 128, 128, 4, 1, 1, 8, 64, 16, 1, 16, 4, 32),
- (64, 128, 128, 4, 1, 1, 8, 128, 64, 1, 8, 8, 8),
- (64, 128, 128, 4, 1, 2, 4, 64, 128, 4, 2, 4, 4),
- (64, 128, 128, 64, 2, 2, 32, 64, 32, 1, 1, 2, 32),
- (64, 128, 128, 4, 1, 2, 8, 8, 64, 32, 2, 32, 16),
- (64, 128, 128, 4, 1, 2, 32, 4, 32, 4, 4, 4, 4),
- )
- for ((params, isGood) <- Seq((badParameters, false), (goodParameters, true))) {
- params.foreach { case cfg@(n, m, o, v3, v4, v5, v6, v7, v8, ls0, ls1, gs0, gs1) =>
- val map = Map(
- nIdent -> n,
- mIdent -> m,
- oIdent -> o,
- TuningParameter("v3") -> v3,
- TuningParameter("v4") -> v4,
- TuningParameter("v5") -> v5,
- TuningParameter("v6") -> v6,
- TuningParameter("v7") -> v7,
- TuningParameter("v8") -> v8,
- TuningParameter("ls0") -> ls0,
- TuningParameter("ls1") -> ls1,
- TuningParameter("gs0") -> gs0,
- TuningParameter("gs1") -> gs1,
- )
- if (autotune.constraints.checkConstraints(constraints, map) != isGood) {
- val (sat, notSat) = constraints.partition(c =>
- c.substitute(map.toMap[ArithExpr, ArithExpr]).isSatisfied())
- println("satisfied:")
- sat.foreach(println)
- println("not satisfied:")
- notSat.foreach(println)
- throw new Exception(s"$cfg should${if (isGood) "" else " not"} pass constraint checking")
- }
- }
- }
- }
-
- test("generateJSON") {
- val parameters = autotune.constraints.collectParameters(convolution)
- val constraints = autotune.constraints.collectConstraints(convolution, parameters)
- val json = autotune.configFileGeneration.generateJSON(parameters, constraints, Tuner(main(32)))
-
- // scalastyle:off
- val gold =
- """{
- | "application_name" : "RISE",
- | "optimization_objectives" : ["runtime"],
- | "hypermapper_mode" : {
- | "mode" : "client-server"
- | },
- | "feasible_output" : {
- | "enable_feasible_predictor" : true,
- | "name" : "Valid",
- | "true_value" : "True",
- | "false_value" : "False"
- | },
- | "design_of_experiment" : {
- | "doe_type" : "random sampling",
- | "number_of_samples" : 20
- | },
- | "optimization_iterations" : 100,
- | "input_parameters" : {
- | "tuned_tile" : {
- | "parameter_type" : "ordinal",
- | "values" : [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
- | },
- | "tuned_vec" : {
- | "parameter_type" : "ordinal",
- | "values" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
- | }
- | }
- |}
- |""".stripMargin
- // scalastyle:on
-
- assert(json.equals(gold))
- }
-
- test("wrapOclRun") {
- val wrapped = wrapOclRun(LocalSize(1), GlobalSize(32))(convolution)
- assert(convolutionOcl.toExpr =~= wrapped)
-
- val e = (wrapped: ToBeTyped[Expr]) (32)
- assert(convolutionOcl(32).toExpr =~= e.toExpr)
- }
-
-
- test("search") {
- // test full tuning run
- val e: Expr = convolutionOcl(32)
-
- val tuningResult = autotune.search(Tuner(main(32), 100))(e)
-
- println("tuningResult: \n")
- tuningResult.samples.foreach(elem => println(elem))
-
- val bestSample = autotune.getBest(tuningResult.samples)
- println("bestSample: \n" + bestSample)
-
- autotune.saveSamples("autotuning/RISE.csv", tuningResult)
- }
-
- // test Hypermapper constraints support
- // needs access to hypermapper_dev repository
- ignore("search experimental") {
- val e: Expr = convolutionOclGsLs(1024)
-
- val tuner = Tuner(
- main = main(1024),
- iterations = 1000,
- name = "RISE",
- output = "autotuning",
- timeouts = Timeouts(5000, 5000, 5000),
- configFile = None,
- hierarchicalHM = true
- )
-
- val tuningResult = autotune.search(tuner)(e)
-
- println("tuningResult: \n")
- tuningResult.samples.foreach(elem => println(elem))
-
- val bestSample = autotune.getBest(tuningResult.samples)
- println("bestSample: \n" + bestSample)
-
- autotune.saveSamples("autotuning/RISE.csv", tuningResult)
- }
-
- test("distribute constraints") {
- val e: Expr = convolutionOclGsLs(1024)
- val params = autotune.constraints.collectParameters(e)
- val constraints = autotune.constraints.collectConstraints(e, params)
-
- val paramsSorted = params.toSeq.sortBy(_.name)
- val gs0 = paramsSorted(0)
- val gs1 = paramsSorted(1)
- val ls0 = paramsSorted(2)
- val ls1 = paramsSorted(3)
- val tile = paramsSorted(4)
- val vec = paramsSorted(5)
-
- val constraintsSorted = constraints.toSeq.sortBy(_.toString)
-
- val gold = Map(
- gs0 -> (Set(constraintsSorted(3), constraintsSorted(4)), Set(ls0)),
- gs1 -> (Set(constraintsSorted(5), constraintsSorted(6)), Set(ls1)),
- ls0 -> (Set(constraintsSorted(7)), Set.empty[NatIdentifier]),
- ls1 -> (Set(constraintsSorted(8)), Set.empty[NatIdentifier]),
- tile -> (Set(constraintsSorted(0), constraintsSorted(1), constraintsSorted(9)), Set(vec)),
- vec -> (Set(constraintsSorted(10), constraintsSorted(11)), Set.empty[NatIdentifier])
- )
-
- val distribution = autotune.configFileGeneration.distributeConstraints(params, constraints)
-
- // check if distribution contains cycle
- assert(check_no_cycle(distribution))
-
- // check distribution against gold (which distribution to expect)
- println("\ndistribution: " )
- distribution.foreach(println)
-
- println("\ngold: " )
- gold.foreach(println)
-
- var size = 0
- distribution.foreach(elem => {
- size += elem._2._1.size
- assert(gold.apply(elem._1)._1.equals(elem._2._1))
- assert(gold.apply(elem._1)._2.equals(elem._2._2))
- })
-
- // we drop one constraint, which is static
- assert(size.equals(constraintsSorted.size-1))
-
- }
-
- test("test cycle checker"){
-
- val emptyConstraints = Set.empty[constraints.Constraint]
-
- val A = NatIdentifier("A")
- val B = NatIdentifier("B")
- val C = NatIdentifier("C")
-
- // create example with no cycle
- val distributionNoCycle = scala.collection.mutable.Map[NatIdentifier,
- (Set[constraints.Constraint], Set[NatIdentifier])]()
- val dependenciesNoCycleA = Set(B)
- val dependenciesNoCycleB = Set.empty[NatIdentifier]
- val dependenciesNoCycleC = Set(A)
-
- distributionNoCycle(A) = (emptyConstraints, dependenciesNoCycleA)
- distributionNoCycle(B) = (emptyConstraints, dependenciesNoCycleB)
- distributionNoCycle(C) = (emptyConstraints, dependenciesNoCycleC)
-
- assert(check_no_cycle(distributionNoCycle.toMap))
-
- // create example with cycle
- val distributionCycle = scala.collection.mutable.Map[NatIdentifier,
- (Set[constraints.Constraint], Set[NatIdentifier])]()
- val dependenciesCycleA = Set(B)
- val dependenciesCycleB = Set(A)
- val dependenciesCycleC = Set.empty[NatIdentifier]
-
- distributionCycle(A) = (emptyConstraints, dependenciesCycleA)
- distributionCycle(B) = (emptyConstraints, dependenciesCycleB)
- distributionCycle(C) = (emptyConstraints, dependenciesCycleC)
-
- assert(!check_no_cycle(distributionCycle.toMap))
-
- // create another example with cycle
- val distributionCycle2 = scala.collection.mutable.Map[NatIdentifier,
- (Set[constraints.Constraint], Set[NatIdentifier])]()
- val dependenciesCycle2A = Set(B)
- val dependenciesCycle2B = Set(B)
- val dependenciesCycle2C = Set.empty[NatIdentifier]
-
- distributionCycle2(A) = (emptyConstraints, dependenciesCycle2A)
- distributionCycle2(B) = (emptyConstraints, dependenciesCycle2B)
- distributionCycle2(C) = (emptyConstraints, dependenciesCycle2C)
-
- assert(!check_no_cycle(distributionCycle2.toMap))
-
- }
-
- test("execute convolution") {
- val goodParameters: Map[Nat, Nat] = Map(
- TuningParameter("vec") -> (4: Nat),
- TuningParameter("tile") -> (16: Nat)
- )
-
- val e: Expr = convolutionOcl(32)
- val e2 = rise.core.substitute.natsInExpr(goodParameters, e)
-
- val result = autotune.execution.execute(e2, main(32), Timeouts(5000, 5000, 5000))
-
- // check if result has valid runtime
- assert(result._1.isDefined)
- // check if no error was reported
- assert(result._2.errorLevel.equals(autotune.NO_ERROR))
-
- println("result: " + result)
- }
-
- test("execute scal") {
- val e: Expr = scalOcl(32)
-
- // scalastyle:off
- val main =
- """
- const int N = 32;
- int main(int argc, char** argv) {
- Context ctx = createDefaultContext();
- Buffer input = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_READ);
- Buffer output = createBuffer(ctx, N * sizeof(float), HOST_READ | HOST_WRITE | DEVICE_WRITE);
-
- float* in = hostBufferSync(ctx, input, N * sizeof(float), HOST_WRITE);
- for (int i = 0; i < N; i++) {
- in[i] = 1;
- }
-
- foo_init_run(ctx, output, input, 4);
-
- float* out = hostBufferSync(ctx, output, N * sizeof(float), HOST_READ);
-
- for (int i = 0; i < N; i++) {
- if (out[i] != 4) {
- fprintf(stderr, "wrong output: %f\n", out[i]);
- exit(EXIT_FAILURE);
- }
- }
-
- destroyBuffer(ctx, input);
- destroyBuffer(ctx, output);
- destroyContext(ctx);
- return EXIT_SUCCESS;
- }
- """
- // scalastyle:on
-
- val result = autotune.execution.execute(e, main, Timeouts(5000, 5000, 5000))
-
- // check if result has valid runtime
- assert(result._1.isDefined)
- // check if no error was reported
- assert(result._2.errorLevel == autotune.NO_ERROR)
-
- println("result: \n" + result)
- }
-
- test("test xml parsing") {
-
- // scalastyle:off
- val xmlString =
- """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- """
- // scalastyle:on
- assert(autotune.execution.getRuntimeFromClap(xmlString).value.toFloat == 0.010112f)
- }
-
- test("text xml parsing with corrupted xml string") {
- // scalastyle:off
- val corruptedXmlString =
- """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- """
- // scalastyle:on
- assert(autotune.execution.getRuntimeFromClap(corruptedXmlString).value.toFloat == 0.158819f)
- }
-
- test("generate huge amount of code") {
- // expression
- val e: Expr = convolutionOclGsLs(1024)
-
- // define parameters to break the code-gen
- val parameters: Map[Nat, Nat] = Map(
- TuningParameter("vec") -> (16: Nat),
- TuningParameter("tile") -> (32: Nat),
- TuningParameter("gs0") -> (1: Nat),
- TuningParameter("gs1") -> (512: Nat),
- TuningParameter("ls0") -> (1: Nat),
- TuningParameter("ls1") -> (64: Nat)
- )
-
- // substitute parameters
- val eWithParams = rise.core.substitute.natsInExpr(parameters, e)
-
- println("run codegen with timeout ")
- // WARNING: timeout does not stop the thread, it only returns to the host thread
- val result = autotune.execution.execute(
- eWithParams,
- main(1024),
- Timeouts(5000, 5000, 5000)
- )
-
- print("result: " + result)
- assert(result._2.errorLevel.equals(autotune.CODE_GENERATION_ERROR))
- }
-}