WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

Commit 2ed6de2a authored by John Zhang's avatar John Zhang
Browse files

refactor: a Callback class to capture configuration and compilation of callback library

parent 9195b4f9
#!/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.
# Functions to configure callback settings
import sys
import logging
from pathlib import Path
import crayons
from mubench import CALLBACKS_DIR
from mubench.util import expandenv, run_in_subproc, ExecutionFailure
logger = logging.getLogger(__name__)
class Callback:
def __init__(self, conf_d, ts):
for key in conf_d:
setattr(self, key, conf_d[key])
libext = '.dylib' if sys.platform == 'darwin' else '.so'
self.dylib = 'libcb_%(name)s' % conf_d + libext # full path set later at compile_dylib
self.configure(ts)
def configure(self, ts):
pass
def compile_dylib(self, output_dir, env):
self.dylib = output_dir / self.dylib
cmd = []
cmd.append(env.get('CC', 'clang'))
cmd.extend(['-shared', '-fPIC'])
# include_dirs
cmd.extend(map(lambda s: '-I' + s, self.include_dirs))
# library_dirs
cmd.extend(map(lambda s: '-L' + s, self.library_dirs))
# libraries
cmd.extend(map(lambda s: '-l' + s, self.libraries))
# flags
cmd.extend(self.flags)
# output
cmd.extend(['-o', self.dylib])
# source
cmd.append(CALLBACKS_DIR / ('cb_%s.c' % self.name))
cmd.extend(self.extra_srcs)
try:
run_in_subproc(cmd, env)
except ExecutionFailure as e:
logger.info('Compiling callback library ' + crayons.red('FAILED'))
logger.critical(crayons.red(str(e)))
errlog_file = output_dir / 'libcb.log'
e.dump(errlog_file)
logger.info('error output written to %s' % errlog_file)
exit(1)
return self.dylib
def extract_stat(self, stdout, stderr):
pass
def __getitem__(self, key):
return getattr(self, key)
class ClockCallback(Callback):
def extract_stat(self, stdout, stderr):
return float(stdout.split()[-1])
class PrintCallback(Callback):
pass
class PerfEventCallback(Callback):
def configure(self, ts):
assert hasattr(self, 'libpfm4_dir'), "libpfm4 install directory not specified"
libpfm4 = Path(expandenv(self.libpfm4_dir, ts.env))
if not libpfm4.is_absolute():
libpfm4 = CALLBACKS_DIR / libpfm4 # default relative to CALLBACKS_DIR
self.include_dirs.extend([
str(libpfm4 / 'include'),
str(libpfm4 / 'util')
])
self.library_dirs.append(str(libpfm4 / 'lib'))
self.libraries.append('pfm')
self.extra_srcs.append(str(libpfm4 / 'util' / 'perf_util.c'))
self.flags.append('-pthread')
def extract_stat(self, stdout, stderr):
raise NotImplementedError
CALLBACK_BY_NAME = {
'clock': ClockCallback,
'print': PrintCallback,
'perfevnet': PerfEventCallback,
}
#!/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.
# Functions to configure callback settings
from pathlib import Path
from mubench import CALLBACKS_DIR
from mubench.util import expandenv
def configure_cb_perfevent(cb_d, env):
assert 'libpfm4_dir' in cb_d, "libpfm4 install directory not specified"
libpfm4 = Path(expandenv(cb_d['libpfm4_dir'], env))
if not libpfm4.is_absolute():
libpfm4 = CALLBACKS_DIR / libpfm4 # default relative to CALLBACKS_DIR
cb_d['include_dirs'].extend([
str(libpfm4 / 'include'),
str(libpfm4 / 'util')
])
cb_d['library_dirs'].append(str(libpfm4 / 'lib'))
cb_d['libraries'].append('pfm')
cb_d['extra_srcs'].append(str(libpfm4 / 'util' / 'perf_util.c'))
cb_d['flags'].append('-pthread')
def configure_cb_clock(cb_d, env):
pass
def configure_cb_print(cb_d, env):
pass
\ No newline at end of file
......@@ -29,7 +29,7 @@ from mubench.util import expandenv, dictify, run_in_subproc, ExecutionFailure
from mubench.util import add_path_to_ld_library_path
from mubench.lang import get_lang, Language
from mubench.models.result import Result
from mubench.models import cbconf
from mubench.models.callback import CALLBACK_BY_NAME
logger = logging.getLogger(__name__)
......@@ -47,7 +47,6 @@ class TaskSet:
self.name = name
self.benchmark = benchmark
self.iterations = iterations
self.callback = callback
self.runnerwrap = runnerwrap
self.output_dir = kwds['output_dir']
self.resfile = kwds['resfile']
......@@ -63,10 +62,6 @@ class TaskSet:
ts_env[v] = expandenv(ts_env[v], self.env)
self.env.update(ts_env)
# configure callback
conf_func = getattr(cbconf, 'configure_cb_%(name)s' % callback)
conf_func(callback, self.env)
# expand environs in benchmark args and callback param and paths
def get_expanded_list(l):
return list(map(lambda a: expandenv(str(a), self.env), l))
......@@ -77,12 +72,12 @@ class TaskSet:
callback['library_dirs'] = get_expanded_list(callback['library_dirs'])
callback['extra_srcs'] = get_expanded_list(callback['extra_srcs'])
self.callback = CALLBACK_BY_NAME[callback['name']](callback, self)
# compiled callback shared library
libext = '.dylib' if sys.platform == 'darwin' else '.so'
add_path_to_ld_library_path(str(self.output_dir), self.env)
self.callback['dylib'] = self.output_dir / ('libcb_%(name)s' % self.callback + libext)
for d in self.callback['library_dirs']:
for d in self.callback.library_dirs:
add_path_to_ld_library_path(d, self.env)
@staticmethod
......@@ -151,7 +146,7 @@ class TaskSet:
def run(self, skipcomp_l):
# compile callback into shared library first
self.compile_callback()
libcb = self.callback.compile_dylib(self.output_dir, self.env)
# compile first
targets = {}
......@@ -172,8 +167,8 @@ class TaskSet:
logger.critical(crayons.red(str(e)))
errlog_file = self.output_dir / (task.name + '.log')
e.dump(errlog_file)
task_print(task.name, crayons.red(
'error output written to %s' % errlog_file))
task_print(task.name,
crayons.red('error output written to %s' % errlog_file))
# run
data = {t: [] for t in targets} # only run tasks that have a target
......@@ -201,12 +196,11 @@ class TaskSet:
'error output written to %s' % errlog_file))
del data[task]
self.callback['dylib'] = str(self.callback['dylib']) # convert into string for dumping
record = {
'name': self.name,
'iterations': self.iterations,
'benchmark': self.benchmark,
'callback': self.callback,
'callback': {k: self.callback[k] for k in ('name', 'param')},
'results': {t.name: data[t] for t in data},
}
......@@ -220,35 +214,7 @@ class TaskSet:
self.results = {task.name: task.get_result() for task in data}
return self.results
# TODO: debug
def compile_callback(self):
cmd = []
cc = self.env.get('CC', 'clang')
cmd.append(cc)
cmd.extend(['-shared', '-fPIC'])
# include_dirs
cmd.extend(map(lambda s: '-I' + s, self.callback['include_dirs']))
# library_dirs
cmd.extend(map(lambda s: '-L' + s, self.callback['library_dirs']))
# libraries
cmd.extend(map(lambda s: '-l' + s, self.callback['libraries']))
# flags
cmd.extend(self.callback['flags'])
# output
cmd.extend(['-o', self.callback['dylib']])
# source
cmd.append(CALLBACKS_DIR / ('cb_%(name)s.c' % self.callback))
cmd.extend(self.callback['extra_srcs'])
run_in_subproc(cmd, self.env)
class Task:
"""
......@@ -313,17 +279,7 @@ class Task:
# Results and data should not be part of a taskset/task,
# but rather the Result should be *about* a TaskSet
def add_datapoint(self, stdout, stderr, t_proc):
if self.callback['name'] == 'clock':
try:
dp = float(stdout.split()[-1])
except:
raise RuntimeError(
"Cannot extract duration from last line of stdout")
else:
msg = "'%(name)s' callback output processing not implemented" % self.callback
raise NotImplementedError(msg)
self.data_callback.append(dp)
self.data_callback.append(self.callback.extract_stat(stdout, stderr))
self.data_t_proc.append(float(t_proc))
def aggregate_datapoint(self):
......
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