mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-10-31 07:04:17 +00:00 
			
		
		
		
	workloads: add meabo
Add automation for meabo micro-benchmark.
This commit is contained in:
		
				
					committed by
					
						 Marc Bonnici
						Marc Bonnici
					
				
			
			
				
	
			
			
			
						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) | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user