Commit 0690f5ad authored by Martin Bauer's avatar Martin Bauer
Browse files

Added function to run compiled C benchmark code

parent f6ef4d88
from .kerncraft_interface import PyStencilsKerncraftKernel, KerncraftParameters
from .generate_benchmark import generate_benchmark, run_c_benchmark
__all__ = ['PyStencilsKerncraftKernel', 'KerncraftParameters']
__all__ = ['PyStencilsKerncraftKernel', 'KerncraftParameters', 'generate_benchmark', 'run_c_benchmark']
from jinja2 import Template
import os
import subprocess
from pystencils.include import get_pystencils_include_path
from pystencils.cpu.cpujit import get_compiler_config, run_compile_step
from pystencils.backends.cbackend import generate_c, get_headers
from pystencils.sympyextensions import prod
from pystencils.data_types import get_base_type
......@@ -10,6 +14,8 @@ benchmark_template = Template("""
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include <stdio.h>
{{ includes }}
{%- if likwid %}
......@@ -18,7 +24,8 @@ benchmark_template = Template("""
#define RESTRICT __restrict__
void dummy(double *);
void dummy(void *);
void timing(double* wcTime, double* cpuTime);
extern int var_false;
......@@ -72,19 +79,30 @@ int main(int argc, char **argv)
{%- endif %}
{%- if timing %}
double wcStartTime, cpuStartTime, wcEndTime, cpuEndTime;
timing(&wcStartTime, &cpuStartTime);
{%- endif %}
for (; repeat > 0; --repeat)
// Dummy calls
{%- for field_name, dataType, size in fields %}
if(var_false) dummy({{field_name}});
if(var_false) dummy((void*){{field_name}});
{%- endfor %}
{%- for constantName, dataType in constants %}
if(var_false) dummy(&{{constantName}});
if(var_false) dummy((void*)&{{constantName}});
{%- endfor %}
{%- if timing %}
timing(&wcEndTime, &cpuEndTime);
if( warmup == 0)
printf("%e\\n", (wcEndTime - wcStartTime) / atoi(argv[1]) );
{%- endif %}
{%- if likwid %}
......@@ -101,7 +119,18 @@ int main(int argc, char **argv)
def generate_benchmark(ast, likwid=False, openmp=False):
def generate_benchmark(ast, likwid=False, openmp=False, timing=False):
"""Return C code of a benchmark program for the given kernel.
ast: the pystencils AST object as returned by create_kernel
likwid: if True likwid markers are added to the code
openmp: relevant only if likwid=True, to generated correct likwid initialization code
timing: add timing output to the code, prints time per iteration to stdout
C code as string
accessed_fields = { f for f in ast.fields_accessed}
constants = []
fields = []
......@@ -135,5 +164,45 @@ def generate_benchmark(ast, likwid=False, openmp=False):
'constants': constants,
'call_argument_list': ",".join(call_parameters),
'includes': includes,
'timing': timing,
return benchmark_template.render(**args)
def run_c_benchmark(ast, inner_iterations, outer_iterations=3):
"""Runs the given kernel with outer loop in C
inner_iterations: timings are recorded around this many iterations
outer_iterations: number of timings recorded
list of times per iterations for each outer iteration
import kerncraft
benchmark_code = generate_benchmark(ast, timing=True)
with open('bench.c', 'w') as f:
kerncraft_path = os.path.dirname(kerncraft.__file__)
extra_flags = ['-I' + get_pystencils_include_path(),
'-I' + os.path.join(kerncraft_path, 'headers')]
compiler_config = get_compiler_config()
compile_cmd = [compiler_config['command']] + compiler_config['flags'].split()
compile_cmd += [*extra_flags,
os.path.join(kerncraft_path, 'headers', 'timing.c'),
os.path.join(kerncraft_path, 'headers', 'dummy.c'),
'-o', 'bench',
results = []
for _ in range(outer_iterations):
benchmark_time = float(subprocess.check_output(['./bench', str(inner_iterations)]))
return results
Supports Markdown
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