mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-31 10:11:17 +00:00
workloads: add meabo
Add automation for meabo micro-benchmark.
This commit is contained in:
parent
f19ca4c00c
commit
b8343e545b
313
wa/workloads/meabo/__init__.py
Normal file
313
wa/workloads/meabo/__init__.py
Normal file
@ -0,0 +1,313 @@
|
||||
# Copyright 2016 ARM Limited
|
||||
#
|
||||
# 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.
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from wa import Workload, Parameter, Executable, ConfigError, WorkloadError
|
||||
from wa.utils.exec_control import once
|
||||
from wa.utils.types import list_of_ints
|
||||
|
||||
|
||||
phase_start_regex = re.compile(r"Starting phase\s+(?P<phase>\d+)")
|
||||
counter_value_regex = re.compile(r"Thread\s+(?P<thread>\d+)\s+(?P<name>\w+)\svalue\s+\=\s+(?P<value>\d+)")
|
||||
duration_regex = re.compile(r"Phase\s+(?P<phase>\d+)[\s\w\(\)]+\:\s+(?P<duration>\d+)")
|
||||
|
||||
|
||||
class Meabo(Workload):
|
||||
|
||||
name = 'meabo'
|
||||
description = '''
|
||||
A multi-phased multi-purpose micro-benchmark. The micro-benchmark is
|
||||
composed of 10 phases that perform various generic calculations (from
|
||||
memory to compute intensive).
|
||||
|
||||
It is a highly configurable tool which can be used for energy efficiency
|
||||
studies, ARM big.LITTLE Linux scheduler analysis and DVFS studies. It can
|
||||
be used for other benchmarking as well.
|
||||
|
||||
All floating-point calculations are double-precision.
|
||||
|
||||
| Phase 1: Floating-point & integer computations with good data locality
|
||||
| Phase 2: Vector multiplication & addition, 1 level of indirection in 1
|
||||
| source vector
|
||||
| Phase 3: Vector scalar addition and reductions
|
||||
| Phase 4: Vector addition
|
||||
| Phase 5: Vector addition, 1 level of indirection in both source vectors
|
||||
| Phase 6: Sparse matrix-vector multiplication
|
||||
| Phase 7: Linked-list traversal
|
||||
| Phase 8: Electrostatic force calculations
|
||||
| Phase 9: Palindrome calculations
|
||||
| Phase 10: Random memory accesses
|
||||
|
||||
For more details and benchmark source, see:
|
||||
|
||||
https://github.com/ARM-software/meabo
|
||||
|
||||
.. note:: current implementation of automation relies on the executable to
|
||||
be either statically linked or for all necessary depencies to be
|
||||
installed on the target.
|
||||
|
||||
'''
|
||||
|
||||
parameters = [
|
||||
Parameter(
|
||||
'array_size',
|
||||
kind=int,
|
||||
description='''
|
||||
Size of arrays used in Phases 1, 2, 3, 4 and 5.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=1048576,
|
||||
),
|
||||
Parameter(
|
||||
'nrow',
|
||||
kind=int,
|
||||
description='''
|
||||
Number of rows for the sparse matrix used in Phase 6.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=16384,
|
||||
),
|
||||
Parameter(
|
||||
'ncol',
|
||||
kind=int,
|
||||
description='''
|
||||
Number of columns for the sparse matrix used in Phase 6.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=16384,
|
||||
),
|
||||
Parameter(
|
||||
'num_iterations',
|
||||
kind=int,
|
||||
description='''
|
||||
Number of iterations that core loop is executed.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=1000,
|
||||
),
|
||||
Parameter(
|
||||
'block_size',
|
||||
kind=int,
|
||||
description='''
|
||||
Block size used in Phase 1.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=8,
|
||||
),
|
||||
Parameter(
|
||||
'num_cpus',
|
||||
kind=int,
|
||||
description='''
|
||||
Number of total CPUs that the application can bind threads to.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=6,
|
||||
),
|
||||
Parameter(
|
||||
'per_phase_cpu_ids',
|
||||
kind=list_of_ints,
|
||||
description='''
|
||||
Sets which cores each phase is run on.
|
||||
''',
|
||||
constraint=lambda x: all(v>=-1 for v in x),
|
||||
default=[-1]*10,
|
||||
),
|
||||
Parameter(
|
||||
'num_hwcntrs',
|
||||
kind=int,
|
||||
description='''
|
||||
Only available when using PAPI. Controls how many hardware counters
|
||||
PAPI will get access to.
|
||||
''',
|
||||
constraint=lambda x: x >= 0,
|
||||
default=7,
|
||||
),
|
||||
Parameter(
|
||||
'run_phases',
|
||||
kind=list_of_ints,
|
||||
description='''
|
||||
Controls which phases to run.
|
||||
''',
|
||||
constraint=lambda x: all(0 < v <=10 for v in x),
|
||||
default=range(1, 11),
|
||||
),
|
||||
Parameter(
|
||||
'num_threads',
|
||||
kind=int,
|
||||
description='''
|
||||
Controls how many threads the application will be using.
|
||||
''',
|
||||
constraint=lambda x: x >= 0,
|
||||
default=0,
|
||||
),
|
||||
Parameter(
|
||||
'bind_to_cpu_set',
|
||||
kind=int,
|
||||
description='''
|
||||
Controls whether threads will be bound to a core set, or each
|
||||
individual thread will be bound to a specific core within the core
|
||||
set.
|
||||
''',
|
||||
constraint=lambda x: 0 <= x <= 1,
|
||||
default=1,
|
||||
),
|
||||
Parameter(
|
||||
'llist_size',
|
||||
kind=int,
|
||||
description='''
|
||||
Size of the linked list available for each thread.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=16777216,
|
||||
),
|
||||
Parameter(
|
||||
'num_particles',
|
||||
kind=int,
|
||||
description='''
|
||||
Number of particles used in Phase 8.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=1048576,
|
||||
),
|
||||
Parameter(
|
||||
'num_palindromes',
|
||||
kind=int,
|
||||
description='''
|
||||
Number of palindromes used in Phase 9.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=1024,
|
||||
),
|
||||
Parameter(
|
||||
'num_randomloc',
|
||||
kind=int,
|
||||
description='''
|
||||
Number of random memory locations accessed in Phase 10.
|
||||
''',
|
||||
constraint=lambda x: x > 0,
|
||||
default=2097152,
|
||||
),
|
||||
Parameter(
|
||||
'run_timeout',
|
||||
kind=int,
|
||||
description="""
|
||||
Timeout for execution of the test.
|
||||
""",
|
||||
constraint=lambda x: x > 0,
|
||||
default=60 * 45,
|
||||
),
|
||||
]
|
||||
|
||||
options = [
|
||||
('-s', 'array_size'),
|
||||
('-B', 'bind_to_cpu_set'),
|
||||
('-b', 'block_size'),
|
||||
('-l', 'llist_size'),
|
||||
('-c', 'ncol'),
|
||||
('-r', 'nrow'),
|
||||
('-C', 'num_cpus'),
|
||||
('-H', 'num_hwcntrs'),
|
||||
('-i', 'num_iterations'),
|
||||
('-x', 'num_palindromes'),
|
||||
('-p', 'num_particles'),
|
||||
('-R', 'num_randomloc'),
|
||||
('-T', 'num_threads'),
|
||||
]
|
||||
|
||||
def validate(self):
|
||||
if len(self.run_phases) != len(self.per_phase_cpu_ids):
|
||||
msg = "Number of phases doesn't match the number of CPU mappings"
|
||||
raise ConfigError(msg)
|
||||
|
||||
def initialize(self, context):
|
||||
self._install_executable(context)
|
||||
self._build_command()
|
||||
|
||||
def setup(self, context):
|
||||
self.output = None
|
||||
|
||||
def run(self, context):
|
||||
self.output = self.target.execute(self.command,
|
||||
timeout=self.run_timeout)
|
||||
|
||||
def update_output(self, context):
|
||||
if self.output is None:
|
||||
self.logger.warning('Did not collect output')
|
||||
return
|
||||
|
||||
outfile = os.path.join(context.output_directory, 'meabo-output.txt')
|
||||
with open(outfile, 'wb') as wfh:
|
||||
wfh.write(self.output)
|
||||
context.add_artifact('meabo-output', outfile, kind='raw')
|
||||
|
||||
cur_phase = 0
|
||||
for line in self.output.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
match = phase_start_regex.search(line)
|
||||
if match:
|
||||
cur_phase = match.group('phase')
|
||||
|
||||
match = counter_value_regex.search(line)
|
||||
if match:
|
||||
if cur_phase == 0:
|
||||
msg = 'Matched thread performance counters outside of phase!'
|
||||
raise WorkloadError(msg)
|
||||
name = 'phase_{}_thread_{}_{}'.format(cur_phase,
|
||||
match.group('thread'),
|
||||
match.group('name'))
|
||||
context.result.add_metric(name, int(match.group('value')))
|
||||
|
||||
match = duration_regex.search(line)
|
||||
if match:
|
||||
context.add_metric("phase_{}_duration".format(match.group('phase')),
|
||||
int(match.group('duration')), units="ns")
|
||||
|
||||
def finalize(self, context):
|
||||
self._uninstall_executable()
|
||||
|
||||
def _build_command(self):
|
||||
self.command = self.target_exe
|
||||
|
||||
# We need to calculate the phase mask
|
||||
phase_mask = 0
|
||||
for phase in self.run_phases:
|
||||
phase_mask |= 1<<(phase-1)
|
||||
|
||||
self.command += ' -P {:d}'.format(phase_mask)
|
||||
|
||||
# Set the CPU ids for each phase we are running
|
||||
for phase, cpu_id in zip(self.run_phases, self.per_phase_cpu_ids):
|
||||
self.command += ' -{0:1d} {1:d}'.format(phase, cpu_id)
|
||||
|
||||
# We need to append extra arguments to the command based on the
|
||||
# parameters passed in from the agenda.
|
||||
for option, param_name in self.options:
|
||||
param_value = getattr(self, param_name, None)
|
||||
if param_value is not None:
|
||||
self.command += ' {} {}'.format(option, param_value)
|
||||
|
||||
@once
|
||||
def _install_executable(self, context):
|
||||
resource = Executable(self, self.target.abi, 'meabo')
|
||||
host_exe = context.resolver.get(resource)
|
||||
Meabo.target_exe = self.target.install(host_exe)
|
||||
|
||||
@once
|
||||
def _uninstall_executable(self):
|
||||
self.target.uninstall_executable(self.target_exe)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user