Commit d50e94e5 authored by Sebastian Kuckuk's avatar Sebastian Kuckuk
Browse files

add initial version of exastencils

parents

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.
target
.cache
.idea
Main authors
====================
Christian Schmitt
Sebastian Kuckuk
Stefan Kronawitter
List of contributors
====================
Alexander Grebhahn
Armin Größlinger
Christoph Wollner
Daniel Zint
David Spitzberg
Denis Ribica
Ewald Flad
Georg Altmann
Hannah Rittich
Harald Köstler
Jonas Schmitt
Lisa Claus
Maik Haase
Markus Obereisenbuchner
Max Gerecke
Meike Blöcher
Richard Angersbach
Thomas Lang
This diff is collapsed.
bin
build
target
.cache
.settings
name := "Compiler"
version := "1.0"
sbtVersion := "1.3.2"
scalaVersion := "2.12.10"
scalaSource in Compile := baseDirectory.value / "src"
resourceDirectory in Compile := baseDirectory.value / "res"
unmanagedBase in Compile := baseDirectory.value / "lib"
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
libraryDependencies += "io.github.kostaskougios" % "cloning" % "1.10.0"
libraryDependencies += "org.objenesis" % "objenesis" % "3.1"
lazy val downloadCImg = taskKey[Unit]("Download CImg header and store it in Compiler/res")
downloadCImg := {
val sourceUrl = "https://framagit.org/dtschump/CImg/raw/master/CImg.h"
val targetFileName = "Compiler/res/CImg.h"
val overwrite = true
if (overwrite || java.nio.file.Files.notExists(new File(targetFileName).toPath)) {
println(s"Downloading CImg header from $sourceUrl")
val targetFile = new java.io.File(targetFileName)
if (!targetFile.getParentFile.exists()) {
println("Setting up directory")
targetFile.getParentFile.mkdirs()
}
try {
val src = scala.io.Source.fromURL(sourceUrl)
val out = new java.io.FileWriter(targetFile)
out.write(src.mkString)
out.close()
} catch {
case e : java.io.IOException => println(s"Error downloading: $e")
}
println("Successful")
} else {
println("CImg header already exists")
}
}
//=============================================================================
//
// This file is part of the ExaStencils code generation framework. ExaStencils
// is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// ExaStencils is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with ExaStencils. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
import scala.collection.mutable.ListBuffer
import exastencils.app._
import exastencils.base.ExaRootNode
import exastencils.config._
import exastencils.core._
import exastencils.core.logger.Logger_HTML
import exastencils.datastructures._
import exastencils.logger._
import exastencils.parsers.config.Settings_Parser
import exastencils.polyhedron.IR_PolyOpt
import exastencils.prettyprinting._
import exastencils.util._
object Main {
def localInitialize(args : Array[String]) = {
//if (Settings.timeStrategies) -> right now this Schroedinger flag is neither true nor false
StrategyTimer.startTiming("Initializing")
StateManager.setRoot(ExaRootNode)
// check from where to read input
val settingsParser = new Settings_Parser(Settings)
val knowledgeParser = new Settings_Parser(Knowledge)
val platformParser = new Settings_Parser(Platform)
if (args.length >= 1)
settingsParser.parseFile(args(0))
if (Settings.produceHtmlLog) Logger_HTML.init() // allows emitting errors and warning in knowledge and platform parsers
if (args.length >= 2)
knowledgeParser.parseFile(args(1))
if (args.length >= 3)
platformParser.parseFile(args(2))
if (args.length >= 4)
IR_PolyOpt.polyOptExplIDs = args(3)
// validate knowledge, etc.
Knowledge.update()
Settings.update()
Platform.update()
// resolve aliases in knowledge, settings and platform
ResolveAlias.apply()
// begin writing log to file after potential alias resolution in filename
if (Settings.produceHtmlLog) Logger_HTML.beginFileWrite()
if (Settings.cancelIfOutFolderExists) {
if (new java.io.File(Settings.getOutputPath).exists()) {
Logger.error(s"Output path ${ Settings.getOutputPath } already exists but cancelIfOutFolderExists is set to true. Shutting down now...")
sys.exit(0)
}
}
// init buildfile generator, overrides settings file
if ("MSVC" == Platform.targetCompiler)
Settings.buildfileGenerators = ListBuffer("ProjectfileGenerator")
if (Settings.timeStrategies)
StrategyTimer.stopTiming("Initializing")
}
def localShutdown() = {
StateManager.root.nodes.clear()
ExaRootNode.clear()
if (Settings.timeStrategies) {
StrategyTimer.print()
StrategyTimer.clear()
}
if (Settings.produceHtmlLog)
Logger_HTML.finish()
ObjectWithStateCollection.clearAll()
}
def print() = {
Logger.dbg("Prettyprinting to folder " + new java.io.File(Settings.getOutputPath).getAbsolutePath)
ExaLayerHandler.ir_handler.print()
PrettyprintingManager.finish()
}
def main(args : Array[String]) : Unit = {
try {
// for runtime measurement
val start : Long = System.nanoTime()
localInitialize(args)
ExaLayerHandler.initializeAllLayers()
ExaLayerHandler.handleAllLayers()
print()
Logger.dbg("Done!")
Logger.dbg("Runtime:\t" + math.round((System.nanoTime() - start) / 1e8) / 10.0 + " seconds")
new CountNodes("number of printed nodes").apply()
ExaLayerHandler.shutdownAllLayers()
localShutdown()
} catch {
case e : LoggerError =>
throw e
case e : Throwable =>
Logger.warn(s"Critical error: ${ e.getMessage }")
Logger.warn(s"Stack trace:\n${ e.getStackTrace.mkString("\n\tat ") }")
if (Settings.produceHtmlLog)
Logger_HTML.finish()
throw e
}
}
}
//=============================================================================
//
// This file is part of the ExaStencils code generation framework. ExaStencils
// is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// ExaStencils is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with ExaStencils. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
package exastencils.app
import exastencils.app.ir._
import exastencils.app.l1._
import exastencils.app.l2._
import exastencils.app.l3._
import exastencils.app.l4._
import exastencils.config.Settings
/// ExaLayerHandler
object ExaLayerHandler {
var l1_handler : L1_LayerHandler = L1_DefaultLayerHandler
var l2_handler : L2_LayerHandler = L2_DefaultLayerHandler
var l3_handler : L3_LayerHandler = L3_DefaultLayerHandler
var l4_handler : L4_LayerHandler = L4_DefaultLayerHandler
var ir_handler : IR_LayerHandler = IR_DefaultLayerHandler
def allLayers = Array(l1_handler, l2_handler, l3_handler, l4_handler, ir_handler)
def maskUnusedLayers() : Unit = {
if (Settings.minLayerFileProvided > 1) l1_handler = L1_DummyLayerHandler
if (Settings.minLayerFileProvided > 2) l2_handler = L2_DummyLayerHandler
if (Settings.minLayerFileProvided > 3) l3_handler = L3_DummyLayerHandler
if (Settings.minLayerFileProvided > 4) l4_handler = L4_DummyLayerHandler
if (Settings.minLayerFileProvided > 5) ir_handler = IR_DummyLayerHandler
}
def initializeAllLayers() : Unit = {
allLayers.foreach(_.initialize())
}
def handleAllLayers() : Unit = {
allLayers.foreach(_.handle())
}
def shutdownAllLayers() : Unit = {
allLayers.foreach(_.shutdown())
}
}
\ No newline at end of file
//=============================================================================
//
// This file is part of the ExaStencils code generation framework. ExaStencils
// is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// ExaStencils is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with ExaStencils. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
package exastencils.app
/// LayerHandler
trait LayerHandler {
def initialize() : Unit
def handle() : Unit
def print() : Unit
def shutdown() : Unit
}
//=============================================================================
//
// This file is part of the ExaStencils code generation framework. ExaStencils
// is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// ExaStencils is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with ExaStencils. If not, see <http://www.gnu.org/licenses/>.
//
//=============================================================================
package exastencils.app.ir
import exastencils.app.LayerHandler
import exastencils.applications.ir.IR_HandleMainApplication
import exastencils.applications.swe.ir.IR_ResolveStationFunctions
import exastencils.base.ExaRootNode
import exastencils.base.ir._
import exastencils.baseExt.ir._
import exastencils.boundary.ir.IR_ResolveBoundaryFunctions
import exastencils.communication.DefaultNeighbors
import exastencils.communication.ir._
import exastencils.config._
import exastencils.domain.ir._
import exastencils.experimental.ir.IR_ResolveGismoFunctions
import exastencils.field.ir._
import exastencils.globals.ir._
import exastencils.grid.ir._
import exastencils.interfacing.ir._
import exastencils.knowledge.ir._
import exastencils.layoutTransformation.ir.IR_LayoutTansformation
import exastencils.operator.ir.IR_ApplyOffsetToStencilFieldAccess
import exastencils.optimization.ir._
import exastencils.parallelization.api.cuda._
import exastencils.parallelization.api.mpi._
import exastencils.parallelization.api.omp._
import exastencils.performance.ir.IR_AddPerformanceEstimates
import exastencils.polyhedron._
import exastencils.prettyprinting.PrintToFile
import exastencils.solver.ir._
import exastencils.stencil.ir._
import exastencils.timing.ir._
import exastencils.util._
import exastencils.util.ir._
import exastencils.visualization.ir._
/// IR_LayerHandler
trait IR_LayerHandler extends LayerHandler
/// IR_DummyLayerHandler
object IR_DummyLayerHandler extends IR_LayerHandler {
def initialize() : Unit = {}
def handle() : Unit = {}
def print() : Unit = {}
def shutdown() : Unit = {}
}
/// IR_DefaultLayerHandler
object IR_DefaultLayerHandler extends IR_LayerHandler {
override def initialize() : Unit = {
// TODO: use KnowledgeContainer structure
}
override def shutdown() : Unit = {
// TODO: use KnowledgeContainer structure; remove IR_ClearKnowledge
IR_ClearKnowledge.apply()
}
override def print() : Unit = {
PrintToFile.apply()
}
override def handle() : Unit = {
IR_ProcessInlineKnowledge.apply()
// add globals - init mpi before cuda since cuda might need mpiRank to choose device
if (Knowledge.mpi_enabled)
MPI_AddGlobals.apply()
if (Knowledge.cuda_enabled)
CUDA_AddGlobals.apply()
DefaultNeighbors.setup()
IR_GlobalCollection.get += IR_AllocateDataFunction(IR_FieldCollection.objects, DefaultNeighbors.neighbors)
IR_ExternalFieldCollection.generateCopyFunction().foreach(IR_UserFunctions.get += _)
// setup transformations for communication
if (Knowledge.comm_enableCommTransformations)
IR_CommTransformationCollection.setup()
// add remaining nodes
ExaRootNode.ir_root.nodes ++= List(
// FunctionCollections
IR_UtilFunctions(),
IR_DomainFunctions(),
IR_CommunicationFunctions(),
// Util
IR_Stopwatch(),
IR_TimerFunctions(),
CImg() // TODO: only if required
)
if (Knowledge.cuda_enabled)
ExaRootNode.ir_root.nodes += CUDA_KernelFunctions()
if (Knowledge.experimental_mergeCommIntoLoops)
IR_MergeCommunicateAndLoop.apply()
IR_GeneralSimplify.doUntilDone() // removes (conditional) calls to communication functions that are not possible
IR_SetupCommunication.firstCall = true
IR_SetupCommunication.apply()
IR_InferDiagAndInverseCallDataTypes.doUntilDone()
IR_HandleMainApplication.apply()
IR_ResolveBoundaryFunctions.apply()
IR_ResolveReadParameters.apply()
IR_ResolveStationFunctions.apply()
IR_ResolveCImgFunctions.apply()
IR_ResolveCharacteristicsFunctions.apply()
IR_ResolveBenchmarkFunctions.apply()
IR_ResolveGismoFunctions.apply()
IR_ResolveVtkPrinters.apply()
IR_ResolvePrintWithReducedPrec.apply()
IR_AdaptTimerFunctions.apply()
if (Knowledge.useFasterExpand)
IR_ExpandInOnePass.apply()
else
IR_Expand.doUntilDone()
// HACK: create discr_h* again if there are no multigrid level and the field size was defined explicitly
// currently this works only if all fields are equally sized
if (Knowledge.domain_rect_generate && Knowledge.maxLevel <= 0) {
def globalSize = IR_DomainCollection.getByIdentifier("global").get.asInstanceOf[IR_DomainFromAABB].aabb
val fLayout : Array[IR_FieldLayoutPerDim] = IR_FieldCollection.objects.head.layout.layoutsPerDim
Knowledge.discr_hx = Array[Double](globalSize.width(0) /
(Knowledge.domain_rect_numFragsTotal_x * Knowledge.domain_fragmentLength_x * fLayout(0).numInnerLayers))
if (Knowledge.dimensionality > 1)
Knowledge.discr_hy = Array[Double](globalSize.width(1) /
(Knowledge.domain_rect_numFragsTotal_y * Knowledge.domain_fragmentLength_y * fLayout(1).numInnerLayers))
if (Knowledge.dimensionality > 2)
Knowledge.discr_hz = Array[Double](globalSize.width(2) /
(Knowledge.domain_rect_numFragsTotal_z * Knowledge.domain_fragmentLength_z * fLayout(2).numInnerLayers))
}
IR_ResolveIntegrateOnGrid.apply()
IR_ResolveEvaluateOnGrid.apply()
IR_ResolveVirtualFieldAccesses.apply()
IR_ResolveLoopOverPoints.apply()
IR_ResolveIntergridIndices.apply()
IR_ApplyOffsetToFieldAccess.apply()
IR_ApplyOffsetToStencilFieldAccess.apply()
// simplify indices modified just now, otherwise equality checks will not work later on
IR_GeneralSimplify.apply()
var convChanged = false
do {
IR_FindStencilConvolutions.changed = false
IR_FindStencilConvolutions.apply()
convChanged = IR_FindStencilConvolutions.changed
IR_WrapStencilConvolutions.apply()
if (Knowledge.useFasterExpand)
IR_ExpandInOnePass.apply()
else
IR_Expand.doUntilDone()
} while (convChanged)
IR_ResolveStencilFunction.apply()
if (Knowledge.experimental_visit_enable)
IR_SetupVisit.apply()
// resolve new virtual field accesses
IR_ResolveIntegrateOnGrid.apply()
IR_ResolveEvaluateOnGrid.apply()
IR_ResolveVirtualFieldAccesses.apply()
IR_ApplyOffsetToFieldAccess.apply()
IR_ApplyOffsetToStencilFieldAccess.apply()
IR_ResolveLoopOverPointsInOneFragment.apply()
IR_ResolveLocalSolve.apply()
IR_GeneralSimplify.doUntilDone()
IR_ExtractMatrices.apply()
IR_SetupMatrixExpressions.apply()
var sthChanged = true
while (sthChanged) {
// TODO: move matrix and vector specific parts of IR_GeneralSimplify to specialized strategy
IR_GeneralSimplify.doUntilDone()
IR_ResolveMatrixFunctions.apply()
sthChanged = IR_ResolveMatrixFunctions.results.last._2.matches > 0
}
IR_GeneralSimplify.doUntilDone()
IR_ResolveMatrixAssignments.apply()
IR_LinearizeMatrices.apply()
IR_SetupCommunication.apply() // handle communication statements generated by loop resolution
IR_TypeInference.warnMissingDeclarations = false
IR_TypeInference.apply() // first sweep to allow for VariableAccess extraction in SplitLoopsForHostAndDevice
if (Knowledge.performance_addEstimation)
IR_AddPerformanceEstimates.apply()
// Prepare all suitable LoopOverDimensions and ContractingLoops. This transformation is applied before resolving
// ContractingLoops to guarantee that memory transfer statements appear only before and after a resolved
// ContractingLoop (required for temporal blocking). Leads to better device memory occupancy.
if (Knowledge.cuda_enabled) {
CUDA_PrepareHostCode.apply()
CUDA_PrepareMPICode.apply()
}
IR_ResolveContractingLoop.apply()
IR_SetupCommunication.apply() // handle communication statements generated by loop resolution
IR_MapStencilAssignments.apply()
IR_ResolveFieldAccess.apply()
if (Knowledge.useFasterExpand)
IR_ExpandInOnePass.apply()
else
IR_Expand.doUntilDone()
IR_ResolveLoopOverFragments.apply()
// resolve constant IVs before applying poly opt
IR_ResolveConstIVs.apply()
IR_SimplifyFloatExpressions.apply()
IR_GeneralSimplify.doUntilDone()
if (Knowledge.opt_conventionalCSE || Knowledge.opt_loopCarriedCSE) {
DuplicateNodes.instances.clear()
DuplicateNodes.printStack = false
DuplicateNodes.apply() // FIXME: only debug
IR_Inlining.apply(true)
IR_CommonSubexpressionElimination.apply()
}
IR_MergeConditions.apply()
if (Knowledge.poly_optLevel_fine > 0)
IR_PolyOpt.apply()
IR_ResolveLoopOverDimensions.apply()
IR_TypeInference.apply() // second sweep for any newly introduced nodes - TODO: check if this is necessary
// Apply CUDA kernel extraction after polyhedral optimizations to work on optimized ForLoopStatements
if (Knowledge.cuda_enabled) {
CUDA_AnnotateLoop.apply()
CUDA_ExtractHostAndDeviceCode.apply()
CUDA_AdaptKernelDimensionality.apply()
CUDA_HandleReductions.apply()
}
IR_LayoutTansformation.apply()
// before converting kernel functions -> requires linearized accesses
IR_LinearizeDirectFieldAccess.apply()
IR_LinearizeExternalFieldAccess.apply()
IR_LinearizeTempBufferAccess.apply()
CUDA_LinearizeReductionDeviceDataAccess.apply()