From 2138b6f98e95677deb0a5d2ed960c72af99020da Mon Sep 17 00:00:00 2001 From: Floris-Jan Willemsen Date: Tue, 24 Oct 2023 13:20:00 +0200 Subject: [PATCH] Reduced cognitive complexity of 'check_restrictions', expanded documentation --- CONTRIBUTING.rst | 1 + kernel_tuner/util.py | 89 +++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index b89ff525b..e92fe83fc 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -61,6 +61,7 @@ Steps with :bash:`sudo` access (e.g. on a local device): * Do not forget to make sure the paths are set correctly. If you're using CUDA, the desired CUDA version should be in :bash:`$PATH`, :bash:`$LD_LIBARY_PATH` and :bash:`$CPATH`. * Re-open the shell for changes to take effect. #. Check if the environment is setup correctly by running :bash:`pytest` and :bash:`nox`. All tests should pass, except if one or more extras has been left out in the previous step, then these tests will skip gracefully. + * [Note]: sometimes, changing the NVIDIA driver privileges is required to read program counters and energy measurements. Check if :bash:`cat /proc/driver/nvidia/params | grep RmProfilingAdminOnly` is set to 1. If so, `follow these steps `__ Cluster setup diff --git a/kernel_tuner/util.py b/kernel_tuner/util.py index 9e4f7b227..51cd5da7a 100644 --- a/kernel_tuner/util.py +++ b/kernel_tuner/util.py @@ -250,55 +250,50 @@ def check_block_size_params_names_list(block_size_names, tune_params): def check_restrictions(restrictions, params: dict, verbose: bool) -> bool: - """Check whether a specific instance meets the search space restrictions.""" - valid = True + """Check whether a specific configuration meets the search space restrictions.""" if callable(restrictions): valid = restrictions(params) - else: - for restrict in restrictions: - try: - # if it's a python-constraint, convert to function and execute - if isinstance(restrict, Constraint): - restrict = convert_constraint_restriction(restrict) - if not restrict(params.values()): - valid = False - break - continue - # if it's a string, fill in the parameters and evaluate - elif isinstance(restrict, str): - if not eval(replace_param_occurrences(restrict, params)): - valid = False - break - continue - # if it's a function, call it - elif callable(restrict): - if not restrict(**params): - valid = False - break - continue - # if it's a tuple, use only the parameters in the second argument to call the restriction - elif (isinstance(restrict, tuple) and len(restrict) == 2 - and callable(restrict[0]) and isinstance(restrict[1], (list, tuple))): - # unpack the tuple - restrict, selected_params = restrict - # look up the selected parameters and their value - selected_params = dict((key, params[key]) for key in selected_params) - # call the restriction - if not restrict(**selected_params): - valid = False - break - continue - # otherwise, raise an error - else: - raise ValueError(f"Unkown restriction type {type(restrict)} ({restrict})") - except ZeroDivisionError: - pass - if not valid and verbose: - print( - "skipping config", - get_instance_string(params), - "reason: config fails restriction", - ) + if not valid and verbose is True: + print(f"skipping config {get_instance_string(params)}, reason: config fails restriction") + return valid + valid = True + for restrict in restrictions: + # Check the type of each restriction and validate accordingly. Re-implement as a switch when Python >= 3.10. + try: + # if it's a python-constraint, convert to function and execute + if isinstance(restrict, Constraint): + restrict = convert_constraint_restriction(restrict) + if not restrict(params.values()): + valid = False + break + # if it's a string, fill in the parameters and evaluate + elif isinstance(restrict, str): + if not eval(replace_param_occurrences(restrict, params)): + valid = False + break + # if it's a function, call it + elif callable(restrict): + if not restrict(**params): + valid = False + break + # if it's a tuple, use only the parameters in the second argument to call the restriction + elif (isinstance(restrict, tuple) and len(restrict) == 2 + and callable(restrict[0]) and isinstance(restrict[1], (list, tuple))): + # unpack the tuple + restrict, selected_params = restrict + # look up the selected parameters and their value + selected_params = dict((key, params[key]) for key in selected_params) + # call the restriction + if not restrict(**selected_params): + valid = False + break + # otherwise, raise an error + else: + raise ValueError(f"Unkown restriction type {type(restrict)} ({restrict})") + except ZeroDivisionError: + logging.debug(f"Restriction {restrict} with configuration {get_instance_string(params)} divides by zero.") + if not valid and verbose is True: + print(f"skipping config {get_instance_string(params)}, reason: config fails restriction") return valid