Skip to content
Snippets Groups Projects
Commit c1acb8b5 authored by Martin Bauer's avatar Martin Bauer
Browse files

Benchmark generation for kerncraft

parent 76fb5eab
No related merge requests found
from jinja2 import Template
from pystencils.cpu import generateC
from pystencils.sympyextensions import prod
from pystencils.types import getBaseType
benchmarkTemplate = Template("""
#include "kerncraft.h"
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
{%- if likwid %}
#include <likwid.h>
{%- endif %}
#define RESTRICT __restrict__
#define FUNC_PREFIX
void dummy(double *);
extern int var_false;
{{kernelCode}}
int main(int argc, char **argv)
{
{%- if likwid %}
likwid_markerInit();
likwid_markerThreadInit();
{%- endif %}
{%- for fieldName, dataType, size in fields %}
// Initialization {{fieldName}}
double * {{fieldName}} = aligned_malloc(sizeof({{dataType}}) * {{size}}, 32);
for (int i = 0; i < {{size}}; ++i)
{{fieldName}}[i] = 0.23;
if(var_false)
dummy({{fieldName}});
{%- endfor %}
{%- for constantName, dataType in constants %}
// Constant {{constantName}}
{{dataType}} {{constantName}};
{{constantName}} = 0.23;
if(var_false)
dummy(& {{constantName}});
{%- endfor %}
int repeat = atoi(argv[1]);
{%- if likwid %}
likwid_markerStartRegion("loop");
{%- endif %}
for (; repeat > 0; --repeat)
{
kernel({{callArgumentList}});
// Dummy calls
{%- for fieldName, dataType, size in fields %}
if(var_false) dummy({{fieldName}});
{%- endfor %}
{%- for constantName, dataType in constants %}
if(var_false) dummy(&{{constantName}});
{%- endfor %}
}
{%- if likwid %}
likwid_markerStopRegion("loop");
{%- endif %}
{%- if likwid %}
likwid_markerClose();
{%- endif %}
}
""")
def generateBenchmark(ast, likwid=False):
accessedFields = {f.name: f for f in ast.fieldsAccessed}
constants = []
fields = []
callParameters = []
for p in ast.parameters:
if not p.isFieldArgument:
constants.append((p.name, str(p.dtype)))
callParameters.append(p.name)
else:
assert p.isFieldPtrArgument, "Benchmark implemented only for kernels with fixed loop size"
field = accessedFields[p.fieldName]
dtype = str(getBaseType(p.dtype))
fields.append((p.fieldName, dtype, prod(field.shape)))
callParameters.append(p.fieldName)
args = {
'likwid': likwid,
'kernelCode': generateC(ast),
'fields': fields,
'constants': constants,
'callArgumentList': ",".join(callParameters),
}
return benchmarkTemplate.render(**args)
...@@ -2,6 +2,7 @@ import sympy as sp ...@@ -2,6 +2,7 @@ import sympy as sp
from collections import defaultdict from collections import defaultdict
import kerncraft.kernel import kerncraft.kernel
from pystencils.cpu import createKernel from pystencils.cpu import createKernel
from pystencils.kerncraft.generate_benchmark import generateBenchmark
from pystencils.transformations import typeAllEquations from pystencils.transformations import typeAllEquations
from pystencils.astnodes import LoopOverCoordinate, SympyAssignment, ResolvedFieldAccess from pystencils.astnodes import LoopOverCoordinate, SympyAssignment, ResolvedFieldAccess
from pystencils.field import Field, getLayoutFromStrides from pystencils.field import Field, getLayoutFromStrides
...@@ -77,6 +78,10 @@ class PyStencilsKerncraftKernel(kerncraft.kernel.Kernel): ...@@ -77,6 +78,10 @@ class PyStencilsKerncraftKernel(kerncraft.kernel.Kernel):
self.check() self.check()
def as_code(self, type_='iaca'):
likwid = type_ == 'likwid'
generateBenchmark(self.ast, likwid)
class KerncraftParameters(DotDict): class KerncraftParameters(DotDict):
def __init__(self): def __init__(self):
...@@ -87,77 +92,6 @@ class KerncraftParameters(DotDict): ...@@ -87,77 +92,6 @@ class KerncraftParameters(DotDict):
self['verbose'] = 0 self['verbose'] = 0
class PyStencilsKerncraftKernelOld(kerncraft.kernel.Kernel):
"""
Implementation of kerncraft's kernel interface for pystencils CPU kernels.
Analyses a list of equations assuming they will be executed on a CPU
- right now it uses only the equations, not the optimized form e.g. expressions
that have been pulled in front of the loop
-
"""
def __init__(self, listOfEquations, typeForSymbol=None):
super(PyStencilsKerncraftKernel, self).__init__()
ast = createKernel(listOfEquations, typeForSymbol=typeForSymbol)
self.ast = ast
fieldsRead, fieldsWritten, assignments = typeAllEquations(listOfEquations, typeForSymbol)
allFields = fieldsRead.union(fieldsWritten)
# Loops
innerLoops = [l for l in ast.atoms(LoopOverCoordinate) if l.isInnermostLoop]
if len(innerLoops) == 0:
raise ValueError("No loop found in pystencils AST")
elif len(innerLoops) > 1:
raise ValueError("pystencils AST contains multiple inner loops - only one can be analyzed")
else:
innerLoop = innerLoops[0]
self._loop_stack = []
curNode = innerLoop
while curNode is not None:
if isinstance(curNode, LoopOverCoordinate):
loopInfo = (curNode.loopCounterSymbol.name, curNode.start, curNode.stop, curNode.step)
self._loop_stack.append(loopInfo)
curNode = curNode.parent
self._loop_stack = list(reversed(self._loop_stack))
# Data sources & destinations
self._sources = defaultdict(list)
self._destinations = defaultdict(list)
for eq in listOfEquations:
for accessesDict, expr in [(self._destinations, eq.lhs), (self._sources, eq.rhs)]:
for fa in expr.atoms(Field.Access):
coord = [sp.Symbol(LoopOverCoordinate.getLoopCounterName(i), positive=True) + off
for i, off in enumerate(fa.offsets)]
coord += list(fa.index)
layout = getLayoutFromStrides(fa.field.strides)
permutedCoord = [coord[i] for i in layout]
accessesDict[fa.field.name].append(permutedCoord)
# Variables (arrays)
for field in allFields:
layout = getLayoutFromStrides(field.strides)
permutedShape = list(field.shape[i] for i in layout)
self.set_variable(field.name, str(field.dtype), permutedShape)
for param in ast.parameters:
if not param.isFieldArgument:
self.set_variable(param.name, str(param.dtype), None)
self._sources[param.name] = [None]
# Datatype
self.datatype = list(self.variables.values())[0][0]
# Flops
operationCount = countNumberOfOperations(listOfEquations)
self._flops = {
'+': operationCount['adds'],
'*': operationCount['muls'],
'/': operationCount['divs'],
}
self.check()
# ------------------------------------------- Helper functions --------------------------------------------------------- # ------------------------------------------- Helper functions ---------------------------------------------------------
......
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