generate_benchmark.py 3.3 KB
Newer Older
1
from jinja2 import Template
2
from pystencils.backends.cbackend import generate_c, get_headers
3
from pystencils.sympyextensions import prod
Martin Bauer's avatar
Martin Bauer committed
4
from pystencils.data_types import get_base_type
5
from pystencils.astnodes import PragmaBlock
6

Martin Bauer's avatar
Martin Bauer committed
7
benchmark_template = Template("""
8
9
10
#include "kerncraft.h"
#include <stdlib.h>
#include <stdint.h>
Martin Bauer's avatar
Martin Bauer committed
11
#include <stdbool.h>
12
#include <math.h>
13
14
{{ includes }}

15
16
17
18
19
20
21
22
23
24
{%- if likwid %}
#include <likwid.h>
{%- endif %}

#define RESTRICT __restrict__
#define FUNC_PREFIX
void dummy(double *);
extern int var_false;


25
{{kernel_code}}
26
27
28
29
30
31
32
33


int main(int argc, char **argv)
{
  {%- if likwid %}
  likwid_markerInit();
  {%- endif %}

Martin Bauer's avatar
Martin Bauer committed
34
  {%- for field_name, dataType, size in fields %}
Martin Bauer's avatar
Martin Bauer committed
35
36

  // Initialization {{field_name}}
37
  double * {{field_name}} = (double *) aligned_malloc(sizeof({{dataType}}) * {{size}}, 64);
38
  for (unsigned long long i = 0; i < {{size}}; ++i)
Martin Bauer's avatar
Martin Bauer committed
39
    {{field_name}}[i] = 0.23;
Martin Bauer's avatar
Martin Bauer committed
40

41
  if(var_false)
Martin Bauer's avatar
Martin Bauer committed
42
43
    dummy({{field_name}});

44
  {%- endfor %}
Martin Bauer's avatar
Martin Bauer committed
45
46
47



48
  {%- for constantName, dataType in constants %}
Martin Bauer's avatar
Martin Bauer committed
49

50
51
52
53
54
  // Constant {{constantName}}
  {{dataType}} {{constantName}};
  {{constantName}} = 0.23;
  if(var_false)
      dummy(& {{constantName}});
Martin Bauer's avatar
Martin Bauer committed
55

56
  {%- endfor %}
Martin Bauer's avatar
Martin Bauer committed
57

58
  int repeat = atoi(argv[1]);
59

Martin Bauer's avatar
Martin Bauer committed
60
  {%- if likwid %}
61
62
63
64
65
66
  {%- if openmp %}
  #pragma omp parallel
  {
  likwid_markerRegisterRegion("loop");
  #pragma omp barrier
  {%- endif %}
67
68
  likwid_markerStartRegion("loop");
  {%- endif %}
Martin Bauer's avatar
Martin Bauer committed
69

70
71
  for (; repeat > 0; --repeat)
  {
72
    {{kernelName}}({{call_argument_list}});
Martin Bauer's avatar
Martin Bauer committed
73
74

    // Dummy calls
Martin Bauer's avatar
Martin Bauer committed
75
    {%- for field_name, dataType, size in fields %}
Martin Bauer's avatar
Martin Bauer committed
76
    if(var_false) dummy({{field_name}});
77
78
79
80
81
    {%- endfor %}
    {%- for constantName, dataType in constants %}
    if(var_false) dummy(&{{constantName}});
    {%- endfor %}
  }
Martin Bauer's avatar
Martin Bauer committed
82
83

  {%- if likwid %}
84
  likwid_markerStopRegion("loop");
85
86
87
  {%- if openmp %}
  }
  {%- endif %}
88
  {%- endif %}
Martin Bauer's avatar
Martin Bauer committed
89
90

  {%- if likwid %}
91
92
93
94
95
96
  likwid_markerClose();
  {%- endif %}
}
""")


97
def generate_benchmark(ast, likwid=False, openmp=False):
Martin Bauer's avatar
Martin Bauer committed
98
    accessed_fields = {f.name: f for f in ast.fields_accessed}
99
100
    constants = []
    fields = []
Martin Bauer's avatar
Martin Bauer committed
101
    call_parameters = []
102
103
104
105
    for p in ast.get_parameters():
        if not p.is_field_parameter:
            constants.append((p.symbol.name, str(p.symbol.dtype)))
            call_parameters.append(p.symbol.name)
106
        else:
107
            assert p.is_field_pointer, "Benchmark implemented only for kernels with fixed loop size"
Martin Bauer's avatar
Martin Bauer committed
108
            field = accessed_fields[p.field_name]
109
            dtype = str(get_base_type(p.symbol.dtype))
Martin Bauer's avatar
Martin Bauer committed
110
111
            fields.append((p.field_name, dtype, prod(field.shape)))
            call_parameters.append(p.field_name)
112

113
114
115
    header_list = get_headers(ast)
    includes = "\n".join(["#include %s" % (include_file,) for include_file in header_list])

116
117
118
119
120
121
    # Strip "#pragma omp parallel" from within kernel, because main function takes care of that
    # when likwid and openmp are enabled
    if likwid and openmp:
        if len(ast.body.args) > 0 and isinstance(ast.body.args[0], PragmaBlock):
            ast.body.args[0].pragma_line = ''

122
123
    args = {
        'likwid': likwid,
124
        'openmp': openmp,
125
        'kernel_code': generate_c(ast, dialect='c'),
Martin Bauer's avatar
Martin Bauer committed
126
        'kernelName': ast.function_name,
127
128
        'fields': fields,
        'constants': constants,
129
        'call_argument_list': ",".join(call_parameters),
130
        'includes': includes,
131
    }
Martin Bauer's avatar
Martin Bauer committed
132
    return benchmark_template.render(**args)