Commit 5fbd4200 authored by Jean-Matthieu Gallard's avatar Jean-Matthieu Gallard
Browse files

KernelGen - refactor call to LIBXSMM through a gemmsGeneratorModel + remove...

KernelGen - refactor call to LIBXSMM through a gemmsGeneratorModel + remove access to controller in models
parent d40c7c0f
......@@ -62,9 +62,9 @@ class Configuration:
}
# choose the BLAS library for the matmul: "None" (= C++ loops), "Libxsmm" or "Eigen"
#matmulLib = "Libxsmm"
matmulLib = "Libxsmm"
#matmulLib = "Eigen"
matmulLib = "None"
#matmulLib = "None"
# set to true to print models runtime
runtimeDebug = False
......@@ -72,7 +72,7 @@ class Configuration:
# prefetching settings
# Experimental, not supported by all kernel
# Will use prefetching to optimize tensor operation (prefetch the next slice of an LoG)
prefetching = "All" # "Inputs", "Outputs", "All"
prefetching = "None" # "None", "Inputs", "Outputs", "All"
prefetchLevel = "_MM_HINT_T0" # intrisic _mm_prefetch locality hint (_MM_HINT_T0 = all level of cache), see compiler header xmmintrin.h
cachelineSize = {
"noarch" : 8,
......
......@@ -26,7 +26,6 @@
import os
import copy
import subprocess
import errno
import time
......@@ -145,6 +144,7 @@ class Controller:
self.config["vectSize"] = Configuration.simdWidth[self.config["architecture"]] #only initialize once architecture has been validated
self.config["cachelineSize"] = Configuration.cachelineSize[self.config["architecture"]] #only initialize once architecture has been validated
self.baseContext = self.generateBaseContext() # default context build from config
self.matmulList = [] #list to store the tupple (fileName, matmulConfig) of all requested Matmul (used for gemmsGeneratorModel)
self.gemmList = [] #list to store the name of all generated gemms (used for gemmsCPPModel)
def validateConfig(self, validArchitectures):
......@@ -194,6 +194,8 @@ class Controller:
context["ghostLayerWidth3D"] = 0 if context["nDim"] == 2 else context["ghostLayerWidth"]
context["nDofG"] = context["ghostLayerWidth"]*2 + context["nDof"]
context["nDofG3D"] = 1 if context["nDim"] == 2 else context["nDofG"]
context["function_utils"] = {"getPadSize": self.getPadSize} # quadratureModel needs access to the controller function to calculate padding size
return context
def getSizeWithPadding(self, sizeWithoutPadding):
......@@ -231,14 +233,14 @@ class Controller:
self.runModel( "configurationParameters", configurationParametersModel.ConfigurationParametersModel(self.baseContext))
if self.config["kernelType"] in ["aderdg", "limiter"]:
self.runModel("quadrature", quadratureModel.QuadratureModel(self.baseContext, self))
self.runModel("quadrature", quadratureModel.QuadratureModel(self.baseContext))
if self.config["kernelType"] == "aderdg":
self.runModel("converter", converterModel.ConverterModel(self.baseContext))
self.runModel("amrRoutines", amrRoutinesModel.AMRRoutinesModel(self.baseContext, self))
self.runModel("amrRoutines", amrRoutinesModel.AMRRoutinesModel(self.baseContext))
self.runModel("deltaDistribution", deltaDistributionModel.DeltaDistributionModel(self.baseContext))
self.runModel("faceIntegral", faceIntegralModel.FaceIntegralModel(self.baseContext))
self.runModel("fusedSTPVI", fusedSpaceTimePredictorVolumeIntegralModel.FusedSpaceTimePredictorVolumeIntegralModel(self.baseContext, self))
self.runModel("fusedSTPVI", fusedSpaceTimePredictorVolumeIntegralModel.FusedSpaceTimePredictorVolumeIntegralModel(self.baseContext))
self.runModel("matrixUtils", matrixUtilsModel.MatrixUtilsModel(self.baseContext))
self.runModel("dgMatrix", dgMatrixModel.DGMatrixModel(self.baseContext))
self.runModel("solutionUpdate", solutionUpdateModel.SolutionUpdateModel(self.baseContext))
......@@ -251,7 +253,7 @@ class Controller:
self.runModel("ghostLayerFilling", fvGhostLayerFillingModel.FVGhostLayerFillingModel(self.baseContext))
self.runModel("ghostLayerFillingAtBoundary", fvGhostLayerFillingAtBoundaryModel.FVGhostLayerFillingAtBoundaryModel(self.baseContext))
self.runModel("boundaryLayerExtraction", fvBoundaryLayerExtractionModel.FVBoundaryLayerExtractionModel(self.baseContext))
self.runModel("solutionUpdate", fvSolutionUpdateModel.FVSolutionUpdateModel(self.baseContext, self))
self.runModel("solutionUpdate", fvSolutionUpdateModel.FVSolutionUpdateModel(self.baseContext))
if self.config["kernelType"] in ["aderdg", "fv"]:
self.runModel("boundaryConditions", boundaryConditionsModel.BoundaryConditionsModel(self.baseContext))
......@@ -260,6 +262,9 @@ class Controller:
self.runModel("riemannSolver", riemannModel.RiemannModel(self.baseContext))
## must be run only after all gemm's configurations have been generated
gemmsGeneratorContext = copy.copy(self.baseContext)
gemmsGeneratorContext["matmulList"] = self.matmulList
self.runModel( "gemmsGenerator", gemmsGeneratorModel.GemmsGeneratorModel(gemmsGeneratorContext))
gemmsContext = copy.copy(self.baseContext)
gemmsContext["gemmList"] = self.gemmList
self.runModel( "gemmsCPP", gemmsCPPModel.GemmsCPPModel(gemmsContext))
......@@ -268,37 +273,15 @@ class Controller:
def runModel(self, name, model):
"""Run the given model and if debug then print runtime"""
start = time.perf_counter()
model.generateCode()
out = model.generateCode()
if out is not None and "matmulList" in out and "fileName" in out:
self.matmulList += map(lambda m: (out["fileName"], m), out["matmulList"])
if out is not None and "gemmList" in out:
self.gemmList += out["gemmList"]
if self.config["runtimeDebug"]:
t = time.perf_counter() - start
print(name+": "+str(t))
def generateGemms(self, outputFileName, matmulConfigList):
"""Generate the gemms with the given config list using LIBXSMM"""
for matmul in matmulConfigList:
# add the gemm name to the list of generated gemm
self.gemmList.append((matmul.baseroutinename, matmul.precision))
prefecthing = "nopf" # No native prefetching supported!
type = "dense" # for plain assembly code (rather than inline assembly) choose dense_asm
commandLineArguments = " " + type + \
" " + os.path.join(self.config["pathToOutputDirectory"], outputFileName) + \
" " + self.config["codeNamespace"] + "::" + matmul.baseroutinename + \
" " + str(matmul.M) + \
" " + str(matmul.N) + \
" " + str(matmul.K) + \
" " + str(matmul.LDA) + \
" " + str(matmul.LDB) + \
" " + str(matmul.LDC) + \
" " + str(matmul.alpha) + \
" " + str(matmul.beta) + \
" " + str(matmul.alignment_A) + \
" " + str(matmul.alignment_C) + \
" " + self.config["architecture"] + \
" " + prefecthing + \
" " + matmul.precision
bashCommand = self.config["pathToLibxsmmGemmGenerator"] + commandLineArguments
subprocess.call(bashCommand.split())
def symlinkBLASlib(self):
if self.config["useEigen"]:
......
__all__ = ["adjustSolutionModel", "amrRoutinesModel", "boundaryConditionsModel", "configurationParametersModel", "converterModel", "deltaDistributionModel", "dgMatrixModel", "faceIntegralModel", "fusedSpaceTimePredictorVolumeIntegralModel", "fvBoundaryLayerExtractionModel", "fvGhostLayerFillingModel", "fvGhostLayerFillingAtBoundaryModel", "fvSolutionUpdateModel", "gemmsCPPModel", "kernelsHeaderModel", "limiterModel", "matrixUtilsModel", "quadratureModel", "riemannModel", "solutionUpdateModel", "stableTimeStepSizeModel", "surfaceIntegralModel"]
__all__ = ["adjustSolutionModel", "amrRoutinesModel", "boundaryConditionsModel", "configurationParametersModel", "converterModel", "deltaDistributionModel", "dgMatrixModel", "faceIntegralModel", "fusedSpaceTimePredictorVolumeIntegralModel", "fvBoundaryLayerExtractionModel", "fvGhostLayerFillingModel", "fvGhostLayerFillingAtBoundaryModel", "fvSolutionUpdateModel", "gemmsCPPModel", "gemmsGeneratorModel", "kernelsHeaderModel", "limiterModel", "matrixUtilsModel", "quadratureModel", "riemannModel", "solutionUpdateModel", "stableTimeStepSizeModel", "surfaceIntegralModel"]
......@@ -51,14 +51,13 @@ class AbstractModelBaseClass():
controler during generateCode()
"""
def __init__(self, baseContext, baseController=None):
def __init__(self, baseContext):
self.context = copy.copy(baseContext) # copy the given baseContext as base for the local context
self.controller = baseController # pointer to the controller to generate gemms or get padding size if needed. None by default (if not needed)
self.buildGemmsConfig()
def buildGemmsConfig(self):
"""Generates the list of MaltMult"""
"""Generates the list of MatmulConfigs in the context"""
pass
......
......@@ -26,13 +26,12 @@ from .abstractModelBaseClass import AbstractModelBaseClass
from ..utils import MatmulConfig
class AMRRoutinesModel(AbstractModelBaseClass):
class AMRRoutinesModel(AbstractModelBaseClass):
def generateCode(self):
self.render(("aderdg", "amrRoutines_cpp.template"), "amrRoutines.cpp")
# generates gemms
if(self.context["useLibxsmm"]):
self.controller.generateGemms("asm_amrRoutines.c", self.context["matmulConfigs"].values())
# return required gemms
return {"matmulList": self.context["matmulConfigs"].values(), "fileName": "asm_amrRoutines.c"}
def buildGemmsConfig(self):
......
......@@ -80,9 +80,8 @@ class FusedSpaceTimePredictorVolumeIntegralModel(AbstractModelBaseClass):
else:
self.render(("aderdg", "fusedSPTVI_nonlinear_cpp.template"), "fusedSpaceTimePredictorVolumeIntegral.cpp")
# generates gemms
if self.context["useLibxsmm"]:
self.controller.generateGemms("asm_fstpvi.c", self.context["matmulConfigs"].values())
# return required gemms
return {"matmulList": self.context["matmulConfigs"].values(), "fileName": "asm_fstpvi.c"}
def buildGemmsConfig(self):
......
##
# @file This file is part of the ExaHyPE project.
# @author ExaHyPE Group (exahype@lists.lrz.de)
#
# @section LICENSE
#
# Copyright (c) 2016 http://exahype.eu
# All rights reserved.
#
# The project has received funding from the European Union's Horizon
# 2020 research and innovation programme under grant agreement
# No 671698. For copyrights and licensing, please consult the webpage.
#
# Released under the BSD 3 Open Source License.
# For the full license text, see LICENSE.txt
#
#
# @section DESCRIPTION
#
# Generate the a gemms using LIBXSMM
#
import os
import subprocess
from .abstractModelBaseClass import AbstractModelBaseClass
class GemmsGeneratorModel(AbstractModelBaseClass):
# assune context has a list of matmul config
def generateCode(self):
gemmList = []
for outputFileName,matmul in self.context["matmulList"]:
if self.context["useLibxsmm"]:
gemmList.append(self.generateLIBXSMMgemm(outputFileName,matmul))
return {"gemmList": gemmList}
def generateLIBXSMMgemm(self, outputFileName, matmul):
prefecthing = "nopf" # No native prefetching supported!
type = "dense" # for plain assembly code (rather than inline assembly) choose dense_asm
commandLineArguments = " " + type + \
" " + os.path.join(self.context["pathToOutputDirectory"], outputFileName) + \
" " + self.context["codeNamespace"] + "::" + matmul.baseroutinename + \
" " + str(matmul.M) + \
" " + str(matmul.N) + \
" " + str(matmul.K) + \
" " + str(matmul.LDA) + \
" " + str(matmul.LDB) + \
" " + str(matmul.LDC) + \
" " + str(matmul.alpha) + \
" " + str(matmul.beta) + \
" " + str(matmul.alignment_A) + \
" " + str(matmul.alignment_C) + \
" " + self.context["architecture"] + \
" " + prefecthing + \
" " + matmul.precision
bashCommand = self.context["pathToLibxsmmGemmGenerator"] + commandLineArguments
subprocess.call(bashCommand.split())
return (matmul.baseroutinename, matmul.precision)
......@@ -30,9 +30,9 @@ class LimiterModel(AbstractModelBaseClass):
def generateCode(self):
self.render(("limiter", "limiter_cpp.template"), "limiter.cpp")
# generates gemms
if(self.context["useLibxsmm"]):
self.controller.generateGemms("asm_limiter.c", self.context["matmulConfigs"].values())
# return required gemms
return {"matmulList": self.context["matmulConfigs"].values(), "fileName": "asm_limiter.c"}
def buildGemmsConfig(self):
......
......@@ -30,6 +30,7 @@ from ..utils import MathsUtils #matrix operation and build functions
class QuadratureModel(AbstractModelBaseClass):
def generateCode(self):
if self.context["quadratureType"] == "Gauss-Legendre":
QuadratureWeights, QuadratureNodes = MathsUtils.getGaussLegendre(self.context["nDof"])
OtherQuadratureWeights, OtherQuadratureNodes = MathsUtils.getGaussLobatto(self.context["nDof"])
......@@ -50,21 +51,21 @@ class QuadratureModel(AbstractModelBaseClass):
if(self.context["nDim"] == 2):
# weightsVector is QuadratureWeights itself
weightsVector = MathsUtils.vectorPad(QuadratureWeights, self.controller.getPadSize(len(QuadratureWeights)))
weightsVector = MathsUtils.vectorPad(QuadratureWeights, self.context["function_utils"]["getPadSize"](len(QuadratureWeights)))
self.context["weights2"] = weightsVector
self.context["w2Size"] = len(self.context["weights2"])
self.context["w2_seq"] = range(self.context["w2Size"])
# all combinations of two weights, written as an 1D array
weightsVector = [QuadratureWeights[i] * QuadratureWeights[j] for i in range(self.context["nDof"]) for j in range(self.context["nDof"])]
weightsVector = MathsUtils.vectorPad(weightsVector, self.controller.getPadSize(len(weightsVector)))
weightsVector = MathsUtils.vectorPad(weightsVector, self.context["function_utils"]["getPadSize"](len(weightsVector)))
self.context["weights3"] = weightsVector
self.context["w3Size"] = len(self.context["weights3"])
self.context["w3_seq"] = range(self.context["w3Size"])
# all combinations of three weights, written as an 1D array
weightsVector = [QuadratureWeights[i] * QuadratureWeights[j] * QuadratureWeights[k] for i in range(self.context["nDof"]) for j in range(self.context["nDof"]) for k in range(self.context["nDof"])]
weightsVector = MathsUtils.vectorPad(weightsVector, self.controller.getPadSize(len(weightsVector)))
weightsVector = MathsUtils.vectorPad(weightsVector, self.context["function_utils"]["getPadSize"](len(weightsVector)))
self.context["weights4"] = weightsVector
self.context["w4Size"] = len(self.context["weights4"])
self.context["w4_seq"] = range(self.context["w4Size"])
......@@ -72,21 +73,21 @@ class QuadratureModel(AbstractModelBaseClass):
elif(self.context["nDim"] == 3):
# all combinations of two weights, written as an 1D array
weightsVector = [QuadratureWeights[i] * QuadratureWeights[j] for i in range(self.context["nDof"]) for j in range(self.context["nDof"])]
weightsVector = MathsUtils.vectorPad(weightsVector, self.controller.getPadSize(len(weightsVector)))
weightsVector = MathsUtils.vectorPad(weightsVector, self.context["function_utils"]["getPadSize"](len(weightsVector)))
self.context["weights2"] = weightsVector
self.context["w2Size"] = len(self.context["weights2"])
self.context["w2_seq"] = range(self.context["w2Size"])
# all combination of three weights, written as an 1D array
weightsVector = [QuadratureWeights[i] * QuadratureWeights[j] * QuadratureWeights[k] for i in range(self.context["nDof"]) for j in range(self.context["nDof"]) for k in range(self.context["nDof"])]
weightsVector = MathsUtils.vectorPad(weightsVector, self.controller.getPadSize(len(weightsVector)))
weightsVector = MathsUtils.vectorPad(weightsVector, self.context["function_utils"]["getPadSize"](len(weightsVector)))
self.context["weights3"] = weightsVector
self.context["w3Size"] = len(self.context["weights3"])
self.context["w3_seq"] = range(self.context["w3Size"])
# all combination of four weights, written as an 1D array
weightsVector = [QuadratureWeights[i] * QuadratureWeights[j] * QuadratureWeights[k] * QuadratureWeights[l] for i in range(self.context["nDof"]) for j in range(self.context["nDof"]) for k in range(self.context["nDof"]) for l in range(self.context["nDof"])]
weightsVector = MathsUtils.vectorPad(weightsVector, self.controller.getPadSize(len(weightsVector)))
weightsVector = MathsUtils.vectorPad(weightsVector, self.context["function_utils"]["getPadSize"](len(weightsVector)))
self.context["weights4"] = weightsVector
self.context["w4Size"] = len(self.context["weights4"])
self.context["w4_seq"] = range(self.context["w4Size"])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment