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)) - } -}