20
20
from kernel_tuner .util import check_restrictions as check_instance_restrictions
21
21
from kernel_tuner .util import compile_restrictions , default_block_size_names
22
22
23
- supported_neighbor_methods = ["strictly-adjacent" , "adjacent" , "Hamming" ]
23
+ supported_neighbor_methods = ["strictly-adjacent" , "adjacent" , "Hamming" , "Hamming-adjacent" ]
24
24
25
25
26
26
class Searchspace :
@@ -44,6 +44,7 @@ def __init__(
44
44
strictly-adjacent: differs +1 or -1 parameter index value for each parameter
45
45
adjacent: picks closest parameter value in both directions for each parameter
46
46
Hamming: any parameter config with 1 different parameter value is a neighbor
47
+ Hamming-adjacent: differs +1 or -1 parameter index value for exactly 1 parameter.
47
48
Optionally sort the searchspace by the order in which the parameter values were specified. By default, sort goes from first to last parameter, to reverse this use sort_last_param_first.
48
49
"""
49
50
# set the object attributes using the arguments
@@ -552,6 +553,45 @@ def __get_neighbors_indices_hamming(self, param_config: tuple) -> List[int]:
552
553
matching_indices = (num_matching_params == self .num_params - 1 ).nonzero ()[0 ]
553
554
return matching_indices
554
555
556
+ def __get_neighbors_indices_hammingadjacent (self , param_config_index : int = None , param_config : tuple = None ) -> List [int ]:
557
+ """Get the neighbors using adjacent distance from the parameter configuration (parameter index absolute difference >= 1)."""
558
+ param_config_value_indices = (
559
+ self .get_param_indices (param_config )
560
+ if param_config_index is None
561
+ else self .params_values_indices [param_config_index ]
562
+ )
563
+
564
+ # compute boolean mask for all configuration that differ at exactly one parameter (Hamming distance == 1)
565
+ hamming_mask = np .count_nonzero (self .params_values_indices != param_config_value_indices , axis = 1 ) == 1
566
+
567
+ # get the configuration indices of the hamming neighbors
568
+ hamming_indices , = np .nonzero (hamming_mask )
569
+
570
+ # for the hamming neighbors, calculate the difference between parameter value indices
571
+ hamming_index_difference = self .params_values_indices [hamming_mask ] - param_config_value_indices
572
+
573
+ # for each parameter get the closest upper and lower parameter (absolute index difference >= 1)
574
+ # np.PINF has been replaced by 1e12 here, as on some systems np.PINF becomes np.NINF
575
+ upper_bound = np .min (
576
+ hamming_index_difference ,
577
+ initial = 1e12 ,
578
+ axis = 0 ,
579
+ where = hamming_index_difference > 0 ,
580
+ )
581
+
582
+ lower_bound = np .max (
583
+ hamming_index_difference ,
584
+ initial = - 1e12 ,
585
+ axis = 0 ,
586
+ where = hamming_index_difference < 0 ,
587
+ )
588
+
589
+ # return mask for adjacent neighbors (each parameter is within bounds)
590
+ adjacent_mask = np .all ((lower_bound <= hamming_index_difference ) & (hamming_index_difference <= upper_bound ), axis = 1 )
591
+
592
+ # return hamming neighbors that are also adjacent
593
+ return hamming_indices [adjacent_mask ]
594
+
555
595
def __get_neighbors_indices_strictlyadjacent (
556
596
self , param_config_index : int = None , param_config : tuple = None
557
597
) -> List [int ]:
@@ -615,6 +655,13 @@ def __build_neighbors_index(self, neighbor_method) -> List[List[int]]:
615
655
# for each parameter configuration, find the neighboring parameter configurations
616
656
if self .params_values_indices is None :
617
657
self .__prepare_neighbors_index ()
658
+
659
+ if neighbor_method == "Hamming-adjacent" :
660
+ return list (
661
+ self .__get_neighbors_indices_hammingadjacent (param_config_index , param_config )
662
+ for param_config_index , param_config in enumerate (self .list )
663
+ )
664
+
618
665
if neighbor_method == "strictly-adjacent" :
619
666
return list (
620
667
self .__get_neighbors_indices_strictlyadjacent (param_config_index , param_config )
@@ -667,6 +714,8 @@ def get_neighbors_indices_no_cache(self, param_config: tuple, neighbor_method=No
667
714
self .__prepare_neighbors_index ()
668
715
669
716
# if the passed param_config is fictious, we can not use the pre-calculated neighbors index
717
+ if neighbor_method == "Hamming-adjacent" :
718
+ return self .__get_neighbors_indices_hammingadjacent (param_config_index , param_config )
670
719
if neighbor_method == "strictly-adjacent" :
671
720
return self .__get_neighbors_indices_strictlyadjacent (param_config_index , param_config )
672
721
if neighbor_method == "adjacent" :
0 commit comments