GitLab will be upgraded on 30 Jan 2023 from 2.00 pm (AEDT) to 3.00 pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

rpython.py 5.97 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python3
# Copyright 2017 The Australian National University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

16
17
import subprocess as subproc
import os
18
import sys
19
20
from pathlib import Path

John Zhang's avatar
John Zhang committed
21
22
23
from mubench.lang import Language
from mubench import CALLBACKS_DIR
from mubench.exceptions import ExecutionFailure
24
from mubench.util import expandenv
25

26

27
28
29
30
class RPython(Language):
    name = 'rpython'
    src_ext = 'py'
    compiled = True
31
32
    default_python = 'pypy'  # use pypy by default, it's faster
    default_flags = ['-O3', '--no-shared']
33
    known_impls = ('holstein', 'zebu')
34

35
    @classmethod
John Zhang's avatar
John Zhang committed
36
    def check_lang(cls, lc):
37
38
        assert 'backend' in lc, "backend not specified."
        backend = lc['backend']
John Zhang's avatar
John Zhang committed
39
40
        assert backend in ('c', 'mu'), \
            "invalid backend: %(backend)s." % locals()
41
42
        if backend == 'mu':
            assert 'impl' in lc, "Mu impl needs to be specified for Mu backend."
43
            assert lc['impl'] in cls.known_impls, 'invalid impl: %(impl)s' % lc
44
        return lc
45

46
    @classmethod
John Zhang's avatar
John Zhang committed
47
48
49
    def check_compiler(cls, cc, lc, task):
        env = task.env

50
        # python interpreter
51
52
        python = cc.get('exec', cls.default_python)
        cc['exec'] = expandenv(python, env)
53
54

        # rpython
John Zhang's avatar
John Zhang committed
55
56
57
        assert 'PYPY' in env, 'PYPY needs to be defined in environ'
        pypydir = Path(env['PYPY'])
        rpython_py = pypydir / 'rpython' / 'bin' / 'rpython'
58
        assert rpython_py.exists(), '%(rpython_py)s not found' % locals()
59
60
61
        cc['rpython'] = rpython_py

        # set PYTHONPATH
John Zhang's avatar
John Zhang committed
62
        # include: pypydir, callbacks/rpython
63
64
        pythonpath = env.get('PYTHONPATH', '')
        callback_dir = CALLBACKS_DIR / cls.name
John Zhang's avatar
John Zhang committed
65
        pythonpath = '%(pypydir)s:%(callback_dir)s:%(pythonpath)s' % locals()
66
67
        env['PYTHONPATH'] = pythonpath

68
69
70
71
72
        # check Mu impl environment variable
        if lc['backend'] == 'mu':
            v = 'MU_%s' % (lc['impl'].upper())
            assert v in env, '%s needs to be defined in environ.'

73
        # target configuration arguments
74
        cc['args'] = list(map(lambda a: expandenv(str(a), task.env), cc.get('args', [])))
John Zhang's avatar
John Zhang committed
75
76
77

        # flags
        cc['flags'] = list(map(lambda a: expandenv(a, task.env), cc.get('flags', [])))
78

John Zhang's avatar
John Zhang committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
        if lc['backend'] == 'mu':
            # vmargs
            def set_default_args(defl_d, vmargs):
                # include default args if not specified, otherwise use custom-defined value
                for key, val in defl_d.items():
                    if not any([key in arg for arg in vmargs]):
                        vmargs.append('%(key)s=%(val)s' % locals())
                return vmargs

            vmargs = list(map(lambda a: expandenv(a, task.env), cc.get('vmargs', [])))
            if lc['impl'] == 'holstein':
                separators = '\n'
                default_args = {}
            else:   # zebu
                separators = ' '
                emit_dir = task.output_dir / ('%s_%s-emit' % (task.taskset.name, task.name))
                default_args = {
                    '--aot-emit-dir': str(emit_dir)
                }
            vmargs = set_default_args(default_args, vmargs)
            vmarg_s = separators.join(vmargs)
            cc['vmarg_s'] = vmarg_s

102
103
104
        return cc

    @classmethod
John Zhang's avatar
John Zhang committed
105
106
    def check_runner(cls, rc, lc, task):
        env = task.env
107
        if lc['backend'] == 'mu':
108
            suplibdir = str(task.output_dir)
109
            if sys.platform == 'darwin':
110
                env['DYLD_LIBRARY_PATH'] = suplibdir
111
            else:
112
                env['LD_LIBRARY_PATH'] = suplibdir
113

114
            if lc['impl'] == 'holstein':
115
116
117
118
                mu_holstein_dir = Path(env['MU_HOLSTEIN'])
                default_exec = mu_holstein_dir / 'tools' / 'runmu.sh'
                rc.setdefault('exec', default_exec)
                rc['exec'] = Path(expandenv(str(rc['exec']), env))
119

120
                holstein_default_flags = ['--uPtrHack=True']
John Zhang's avatar
John Zhang committed
121
122
                rc_flags = list(map(lambda a: expandenv(a, task.env), rc.get('flags', [])))
                rc['flags'] = holstein_default_flags + rc_flags
123

124
125
126
127
128
129
        return rc

    @classmethod
    def compile(cls, task):
        cmd = []

John Zhang's avatar
John Zhang committed
130
131
        cmd.append(task.compiler['exec'])
        cmd.append(task.compiler['rpython'])
132
133

        # flags
John Zhang's avatar
John Zhang committed
134
        bk = task.lang['backend']
135
        flags = []
John Zhang's avatar
John Zhang committed
136
        flags.extend(cls.default_flags)
137
        flags.append('--backend=%(bk)s' % locals())
138
        if bk == 'mu':
John Zhang's avatar
John Zhang committed
139
140
            flags.append('--mu-impl=%(impl)s' % task.lang)
            flags.append('--mu-suplibdir=%s' % task.output_dir)
John Zhang's avatar
John Zhang committed
141
            flags.append("--mu-vmargs=%(vmarg_s)s" % task.compiler)
142

John Zhang's avatar
John Zhang committed
143
        flags.extend(task.compiler['flags'])
144
        target = cls.get_default_target(task)
145
146
147
        flags.append('--output=%(target)s' % locals())
        cmd.extend(flags)

John Zhang's avatar
John Zhang committed
148
        cmd.append(task.srcfile)
149

150
        # target configuration arguments
151
152
        # first argument: callback lib
        cmd.append(task.callback['dylib'])
153

154
        # the rest, custom defined arguments
John Zhang's avatar
John Zhang committed
155
        cmd.extend(task.compiler['args'])
156

John Zhang's avatar
John Zhang committed
157
        cls.run_in_subproc(cmd, task.env)
158

159
160
161
162
        assert target.exists()
        return target

    @classmethod
163
    def run(cls, target, task):
164
        cmd = []
John Zhang's avatar
John Zhang committed
165
166
        rc = task.runner
        lc = task.lang
167

John Zhang's avatar
John Zhang committed
168
        if lc['backend'] == 'mu' and lc['impl'] == 'holstein':
169
            cmd.append(rc['exec'])
170
            cmd.extend(rc['flags'])
171

172
        cmd.append(target)
173

174
        # first argument: callback param
John Zhang's avatar
John Zhang committed
175
        cmd.append(task.callback['param'])
176

John Zhang's avatar
John Zhang committed
177
        cmd.extend(task.benchmark['args'])
178

John Zhang's avatar
John Zhang committed
179
        return cls.run_in_subproc(cmd, task.env)