Commit f93688c9 authored by Martin Bauer's avatar Martin Bauer
Browse files

Kerncraft support

parent b3827807
from pystencils.transformations import makeLoopOverDomain, typingFromSympyInspection, \
typeAllEquations, moveConstantsBeforeLoop, getOptimalLoopOrdering
import pystencils.astnodes as ast
from pystencils.backends.cbackend import CBackend, CustomSympyPrinter
from pystencils import TypedSymbol
def createKerncraftCode(listOfEquations, typeForSymbol=None, ghostLayers=None):
Creates an abstract syntax tree for a kernel function, by taking a list of update rules.
Loops are created according to the field accesses in the equations.
:param listOfEquations: list of sympy equations, containing accesses to :class:`pystencils.field.Field`.
Defining the update rules of the kernel
:param typeForSymbol: a map from symbol name to a C type specifier. If not specified all symbols are assumed to
be of type 'double' except symbols which occur on the left hand side of equations where the
right hand side is a sympy Boolean which are assumed to be 'bool' .
:param ghostLayers: a sequence of pairs for each coordinate with lower and upper nr of ghost layers
if None, the number of ghost layers is determined automatically and assumed to be equal for a
all dimensions
:return: :class:`pystencils.ast.KernelFunction` node
if not typeForSymbol:
typeForSymbol = typingFromSympyInspection(listOfEquations, "double")
fieldsRead, fieldsWritten, assignments = typeAllEquations(listOfEquations, typeForSymbol)
allFields = fieldsRead.union(fieldsWritten)
optimalLoopOrder = getOptimalLoopOrdering(allFields)
cstyleLoopOrder = list(range(len(optimalLoopOrder)))
body = ast.Block(assignments)
code = makeLoopOverDomain(body, "kerncraft", ghostLayers=ghostLayers, loopOrder=cstyleLoopOrder)
loopBody = code.body
printer = CBackend(sympyPrinter=ArraySympyPrinter())
FIXED_SIZES = ("XS", "YS", "ZS", "E1S", "E2S")
result = ""
for field in allFields:
sizesPermutation = [FIXED_SIZES[i] for i in field.layout]
suffix = "".join("[%s]" % (size,) for size in sizesPermutation)
result += "%s%s;\n" % (, suffix)
# add parameter definitions
for s in loopBody.undefinedSymbols:
if isinstance(s, TypedSymbol):
result += "%s %s;\n" % (s.dtype,
for element in loopBody.args:
result += printer(element)
result += "\n"
return result
class ArraySympyPrinter(CustomSympyPrinter):
def _print_Access(self, fieldAccess):
Loop = ast.LoopOverCoordinate
coordinateValues = [Loop.getLoopCounterSymbol(i) + offset for i, offset in enumerate(fieldAccess.offsets)]
coordinateValues += list(fieldAccess.index)
permutedCoordinates = [coordinateValues[i] for i in fieldAccess.field.layout]
suffix = "".join("[%s]" % (self._print(a)) for a in permutedCoordinates)
return "%s%s" % (self._print(, suffix)
from .kernel import PyStencilsKerncraftKernel, KerncraftParameters
from .kerncraft_interface import EcmAnalysis, BenchmarkAnalysis
\ No newline at end of file
......@@ -7,6 +7,7 @@ benchmarkTemplate = Template("""
#include "kerncraft.h"
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
{%- if likwid %}
#include <likwid.h>
from tempfile import TemporaryDirectory, TemporaryFile, NamedTemporaryFile
from tempfile import TemporaryDirectory
import sympy as sp
import os
from collections import defaultdict
import subprocess
import kerncraft.kernel
import kerncraft
from iaca_marker import iaca_analyse_instrumented_binary, iaca_instrumentation
import kerncraft.kernel
from kerncraft.machinemodel import MachineModel
from kerncraft.models import ECM, Benchmark
from kerncraft.iaca_marker import iaca_analyse_instrumented_binary, iaca_instrumentation
from pystencils.kerncraft.generate_benchmark import generateBenchmark
from pystencils.astnodes import LoopOverCoordinate, SympyAssignment, ResolvedFieldAccess
from pystencils.field import getLayoutFromStrides
......@@ -108,7 +110,7 @@ class PyStencilsKerncraftKernel(kerncraft.kernel.Kernel):
subprocess.check_output(compilerCmd + [srcFile, '-S', '-o', asmFile])
subprocess.check_output(compilerCmd + [dummySrcFile, '-S', '-o', dummyAsmFile])
instrumentedAsmBlock = iaca_instrumentation(asmFile, pointer_increment='auto')
instrumentedAsmBlock = iaca_instrumentation(asmFile,)
# assemble asm files to executable
subprocess.check_output(compilerCmd + [asmFile, dummyAsmFile, '-o', binaryFile])
......@@ -151,6 +153,43 @@ class KerncraftParameters(DotDict):
self['verbose'] = 0
class Analysis(object):
def __init__(self, ast, kerncraftMachineModel, AnalysisClass, args):
self.ast = ast
if not isinstance(kerncraftMachineModel, MachineModel):
kerncraftMachineModel = MachineModel(kerncraftMachineModel)
self.analysis = AnalysisClass(PyStencilsKerncraftKernel(self.ast),
def results(self):
return self.analysis.results
class EcmAnalysis(Analysis):
def __init__(self, ast, kerncraftMachineModel, cachePredictor='SIM'):
args = KerncraftParameters()
args['cache_predictor'] = cachePredictor
super(EcmAnalysis, self).__init__(ast, kerncraftMachineModel, ECM, args)
def _repr_html(self):
class BenchmarkAnalysis(Analysis):
def __init__(self, ast, kerncraftMachineModel):
super(EcmAnalysis, self).__init__(ast, kerncraftMachineModel, Benchmark, KerncraftParameters())
def _repr_html(self):
# ------------------------------------------- Helper functions ---------------------------------------------------------
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