From 6f5d6516f248ce6a94942f4024264de9852dfc04 Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Fri, 14 Jan 2022 15:25:14 -0500 Subject: [PATCH] teuthology/suite: create nested matrix subsets The general idea is to allow the `%` convolution operator to also subset the resulting matrix. This is done by specifying a number of divisions for the subset in the `%` file. Such as: dir/%: 8 This commit maps a matrix index range of `[0, Subset.size())` to the matrix it is taking a subset of, `[0, Matrix.size())`. To get full coverage, a random number is used to specify "which" subset to use. Contrast with the `--subset` argument to `teuthology-suite` which lets you specify which subset. Signed-off-by: Patrick Donnelly --- teuthology/suite/build_matrix.py | 41 +++++++++++++++++--------------- teuthology/suite/matrix.py | 29 ++++++++++++++++++++++ 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/teuthology/suite/build_matrix.py b/teuthology/suite/build_matrix.py index 2ae78a42be..5de5bd17cb 100644 --- a/teuthology/suite/build_matrix.py +++ b/teuthology/suite/build_matrix.py @@ -33,7 +33,9 @@ def build_matrix(path, subset=None, seed=None): For a directory with a magic '%' file, we generate a result set for each item in the directory, and then do a product to generate - a result list with all combinations (A Product). + a result list with all combinations (A Product). If the file + contains an integer, it is used as the divisor for a random + subset. For a directory with a magic '$' file, or for a directory whose name ends in '$', we generate a list of all items that we will randomly @@ -59,22 +61,13 @@ def build_matrix(path, subset=None, seed=None): def _get_matrix(path, subset=None): - mat = None - first = None - matlimit = None - if subset: - (index, outof) = subset - mat = _build_matrix(path, mincyclicity=outof) - first = (mat.size() // outof) * index - if index == outof or index == outof - 1: - matlimit = mat.size() - else: - matlimit = (mat.size() // outof) * (index + 1) + (which, divisions) = (0,1) if subset is None else subset + if divisions > 1: + mat = _build_matrix(path, mincyclicity=divisions) + mat = matrix.Subset(mat, divisions, which=which) else: - first = 0 mat = _build_matrix(path) - matlimit = mat.size() - return mat, first, matlimit + return mat, 0, mat.size() def _build_matrix(path, mincyclicity=0, item=''): @@ -122,19 +115,29 @@ def _build_matrix(path, mincyclicity=0, item=''): elif '%' in files: # convolve items files.remove('%') + with open(os.path.join(path, '%')) as f: + divisions = f.read() + if len(divisions) == 0: + divisions = 1 + else: + divisions = int(divisions) + assert divisions > 0 submats = [] for fn in sorted(files): submat = _build_matrix( os.path.join(path, fn), - mincyclicity=0, - item=fn) + 0, + fn) if submat is not None: submats.append(submat) mat = matrix.Product(item, submats) - if mat and mat.cyclicity() < mincyclicity: + minc = mincyclicity * divisions + if mat and mat.cyclicity() < minc: mat = matrix.Cycle( - (mincyclicity + mat.cyclicity() - 1) // mat.cyclicity(), mat + (minc + mat.cyclicity() - 1) // mat.cyclicity(), mat ) + if divisions > 1: + mat = matrix.Subset(mat, divisions) return mat else: # list items diff --git a/teuthology/suite/matrix.py b/teuthology/suite/matrix.py index 055c448523..e713bc4433 100644 --- a/teuthology/suite/matrix.py +++ b/teuthology/suite/matrix.py @@ -75,6 +75,35 @@ class Cycle(Matrix): def tostr(self, depth): return '\t'*depth + "Cycle({num}):\n".format(num=self.num) + self.mat.tostr(depth + 1) +# Logically, inverse of Cycle +class Subset(Matrix): + """ + Run a matrix subset. + """ + def __init__(self, mat, divisions, which=None): + self.mat = mat + self.divisions = divisions + if which is None: + self.which = random.randint(0, divisions-1) + else: + assert which < divisions + self.which = which + + def size(self): + return self.mat.size() // self.divisions + + def index(self, i): + i += self.which * self.size() + assert i < self.mat.size() + return self.mat.index(i) + + def minscanlen(self): + return self.mat.minscanlen() + + def tostr(self, depth): + return '\t'*depth + "Subset({num}, {index}):\n".format(num=self.num, index=self.index) + self.mat.tostr(depth + 1) + + class Base(Matrix): """ Just a single item. -- 2.39.5