diff --git a/pyproject.toml b/pyproject.toml index fb3b1ab..117cdd2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ authors = [ ] dependencies = [ - "powerapi[everything] == 2.0.3", + "powerapi[everything] == 2.0.4", "scikit-learn >= 0.20.2", ] diff --git a/src/smartwatts/__init__.py b/src/smartwatts/__init__.py index cb882e3..5f9782c 100644 --- a/src/smartwatts/__init__.py +++ b/src/smartwatts/__init__.py @@ -27,4 +27,4 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -__version__ = "2.1.0" +__version__ = "2.1.1" diff --git a/src/smartwatts/__main__.py b/src/smartwatts/__main__.py index 7b5e69f..7303153 100644 --- a/src/smartwatts/__main__.py +++ b/src/smartwatts/__main__.py @@ -35,12 +35,13 @@ from powerapi import __version__ as powerapi_version from powerapi.backend_supervisor import BackendSupervisor +from powerapi.cli.common_cli_parsing_manager import CommonCLIParsingManager +from powerapi.cli.config_parser import store_true from powerapi.cli.generator import PusherGenerator, PullerGenerator -from powerapi.cli.parser import store_true -from powerapi.cli.tools import CommonCLIParser from powerapi.dispatch_rule import HWPCDispatchRule, HWPCDepthLevel from powerapi.dispatcher import DispatcherActor, RouteTable -from powerapi.exception import PowerAPIException +from powerapi.exception import PowerAPIException, MissingArgumentException, NotAllowedArgumentValueException, \ + FileDoesNotExistException from powerapi.filter import Filter from powerapi.report import HWPCReport @@ -51,38 +52,57 @@ from smartwatts.model import CPUTopology -def generate_smartwatts_parser() -> CommonCLIParser: +def generate_smartwatts_parser() -> CommonCLIParsingManager: """ Construct and returns the SmartWatts cli parameters parser. :return: SmartWatts cli parameters parser """ - parser = CommonCLIParser() + parser_manager = CommonCLIParsingManager() # Formula control parameters - parser.add_argument('disable-cpu-formula', help='Disable CPU formula', flag=True, type=bool, default=False, action=store_true) - parser.add_argument('disable-dram-formula', help='Disable DRAM formula', flag=True, type=bool, default=False, action=store_true) + parser_manager.add_argument_to_cli_parser('disable-cpu-formula', help_text='Disable CPU formula', is_flag=True, + argument_type=bool, default_value=False, action=store_true) + parser_manager.add_argument_to_cli_parser('disable-dram-formula', help_text='Disable DRAM formula', is_flag=True, + argument_type=bool, default_value=False, action=store_true) # Formula RAPL reference event - parser.add_argument('cpu-rapl-ref-event', help='RAPL event used as reference for the CPU power models', default='RAPL_ENERGY_PKG') - parser.add_argument('dram-rapl-ref-event', help='RAPL event used as reference for the DRAM power models', default='RAPL_ENERGY_DRAM') + parser_manager.add_argument_to_cli_parser('cpu-rapl-ref-event', + help_text='RAPL event used as reference for the CPU power models', + default_value='RAPL_ENERGY_PKG') + parser_manager.add_argument_to_cli_parser('dram-rapl-ref-event', + help_text='RAPL event used as reference for the DRAM power models', + default_value='RAPL_ENERGY_DRAM') # CPU topology information - parser.add_argument('cpu-tdp', help='CPU TDP (in Watt)', type=int, default=400) - parser.add_argument('cpu-base-clock', help='CPU base clock (in MHz)', type=int, default=100) - parser.add_argument('cpu-base-freq', help='CPU base frequency (in MHz)', type=int, default=2100) + parser_manager.add_argument_to_cli_parser('cpu-tdp', help_text='CPU TDP (in Watt)', argument_type=int, + default_value=400) + parser_manager.add_argument_to_cli_parser('cpu-base-clock', help_text='CPU base clock (in MHz)', argument_type=int, + default_value=100) + parser_manager.add_argument_to_cli_parser('cpu-base-freq', help_text='CPU base frequency (in MHz)', + argument_type=int, default_value=2100) # Formula error threshold - parser.add_argument('cpu-error-threshold', help='Error threshold for the CPU power models (in Watt)', type=float, default=2.0) - parser.add_argument('dram-error-threshold', help='Error threshold for the DRAM power models (in Watt)', type=float, default=2.0) + parser_manager.add_argument_to_cli_parser('cpu-error-threshold', + help_text='Error threshold for the CPU power models (in Watt)', + argument_type=float, default_value=2.0) + parser_manager.add_argument_to_cli_parser('dram-error-threshold', + help_text='Error threshold for the DRAM power models (in Watt)', + argument_type=float, default_value=2.0) # Sensor information - parser.add_argument('sensor-reports-frequency', help='The frequency with which measurements are made (in milliseconds)', type=int, default=1000) + parser_manager.add_argument_to_cli_parser('sensor-reports-frequency', + help_text='The frequency with which measurements are made (in milliseconds)', + argument_type=int, default_value=1000) # Learning parameters - parser.add_argument('learn-min-samples-required', help='Minimum amount of samples required before trying to learn a power model', type=int, default=10) - parser.add_argument('learn-history-window-size', help='Size of the history window used to keep samples to learn from', type=int, default=60) + parser_manager.add_argument_to_cli_parser('learn-min-samples-required', + help_text='Minimum amount of samples required before trying to learn a power model', + argument_type=int, default_value=10) + parser_manager.add_argument_to_cli_parser('learn-history-window-size', + help_text='Size of the history window used to keep samples to learn from', + argument_type=int, default_value=60) - return parser + return parser_manager def generate_formula_configuration(config: Dict, cpu_topology: CPUTopology, scope: SmartWattsFormulaScope) -> SmartWattsFormulaConfig: @@ -198,6 +218,15 @@ def term_handler(_, __): except InvalidConfigurationParameterException as exn: logging.error('Invalid configuration: %s', exn) sys.exit(1) + except MissingArgumentException as exn: + logging.error('Missing argument: %s', exn) + sys.exit(1) + except NotAllowedArgumentValueException as exn: + logging.error('Not Allowed Argument: %s', exn) + sys.exit(1) + except FileDoesNotExistException as exn: + logging.error('File does not exist: %s', exn) + sys.exit(1) LOGGING_LEVEL = logging.DEBUG if args['verbose'] else logging.INFO LOGGING_FORMAT = '%(asctime)s - %(process)d - %(processName)s - %(name)s - %(levelname)s - %(message)s' diff --git a/src/smartwatts/cli/config_validator.py b/src/smartwatts/cli/config_validator.py index 8373502..4dba317 100644 --- a/src/smartwatts/cli/config_validator.py +++ b/src/smartwatts/cli/config_validator.py @@ -27,8 +27,6 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from typing import Dict - from powerapi.cli import ConfigValidator from smartwatts.exceptions import InvalidConfigurationParameterException @@ -40,9 +38,9 @@ class SmartWattsConfigValidator(ConfigValidator): """ @staticmethod - def validate(config: Dict) -> bool: - if not ConfigValidator.validate(config): - raise InvalidConfigurationParameterException('Invalid PowerAPI parameter') + def validate(config: dict): + + ConfigValidator.validate(config) if config['disable-cpu-formula'] and config['disable-dram-formula']: raise InvalidConfigurationParameterException('At least one of the two formula scope must be enabled') @@ -58,5 +56,3 @@ def validate(config: Dict) -> bool: if config['learn-min-samples-required'] < 0 or config['learn-history-window-size'] < 0: raise InvalidConfigurationParameterException('Report history parameters must be positive') - - return True