From: Luke Kenneth Casson Leighton Date: Thu, 1 Jul 2021 22:54:39 +0000 (+0100) Subject: first matrix-multiply REMAP demo using generators X-Git-Tag: DRAFT_SVP64_0_1~673 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=048381e125bd5c02871d5cdcbf1dbb350e387f2f;p=libreriscv.git first matrix-multiply REMAP demo using generators --- diff --git a/openpower/sv/remap.py b/openpower/sv/remap.py index 387b90ae2..4721d8148 100644 --- a/openpower/sv/remap.py +++ b/openpower/sv/remap.py @@ -10,6 +10,7 @@ VL = xdim * ydim * zdim # set total (can repeat, e.g. VL=x*y*z*4) lims = [xdim, ydim, zdim] idxs = [0,0,0] # starting indices +applydim = [1, 1] # apply lower dims order = [1,0,2] # experiment with different permutations, here offset = 0 # experiment with different offsetet, here invxyz = [0,1,0] # inversion allowed @@ -33,7 +34,11 @@ for idx in range(VL): ix[i] = idxs[i] if invxyz[i]: ix[i] = lims[i] - 1 - ix[i] - new_idx = ix[0] + ix[1] * xdim + ix[2] * xdim * ydim + new_idx = ix[2] + if applydim[1]: + new_idx = new_idx * ydim + ix[1] + if applydim[0]: + new_idx = new_idx * xdim + ix[0] print ("%d->%d" % (idx, new_idx)), break_count += 1 if break_count == lims[order[0]]: diff --git a/openpower/sv/remapmatrix.py b/openpower/sv/remapmatrix.py index 7c94b8947..54d73e93f 100644 --- a/openpower/sv/remapmatrix.py +++ b/openpower/sv/remapmatrix.py @@ -1,13 +1,29 @@ from remapyield import iterate_indices +from functools import reduce +import operator + + +def iterate_triple(SVSHAPE0, SVSHAPE1, SVSHAPE2): + # zip three iterators together, yields a synchronised + # tuple of three indices at a time + yield from zip(iterate_indices(SVSHAPE0), + iterate_indices(SVSHAPE1), + iterate_indices(SVSHAPE2)) + def matrix_demo(): + #### test matrices 1 + # 3x2 matrix X = [[1, 2, 3], [3, 4, 5], ] + # 2x3 matrix Y = [[6, 7], [8, 9], [10, 11], ] + + #### test matrices 2 # 3x3 matrix X = [[12,7,3], [4 ,5,6], @@ -16,23 +32,100 @@ def matrix_demo(): Y = [[5,8,1,2], [6,7,3,0], [4,5,9,1]] + + # get the dimensions of the 2 matrices xdim1 = len(X[0]) ydim1 = len(X) xdim2 = len(Y[0]) ydim2 = len(Y) + + # print out X and Y + print ("X:") + for r in X: + print ("\t", r) + print ("Y:") + for r in Y: + print ("\t", r) + + # first, calculate the result matrix manually. # set up result matrix of correct size result = [] for _ in range(ydim1): result.append([0]*xdim2) - # iterate through rows of X - for i in range(len(X)): - # iterate through columns of Y - for j in range(len(Y[0])): - # iterate through rows of Y - for k in range(len(Y)): + # iterate through rows of Y + for k in range(len(Y)): # ydim2 + # iterate through rows of X + for i in range(len(X)): # ydim1 + # iterate through columns of Y + for j in range(len(Y[0])): # xdim2 + print ("order res %d X %d Y %d" % \ + ((i*xdim2)+j, # result linear array index + (i*xdim1)+k, # X linear array index + (k*xdim2)+j)) # Y linear array index result[i][j] += X[i][k] * Y[k][j] + print ("expected result") for r in result: - print (r) + print ("\t", r) + + # now. flatten the X and Y matrices into linear 1D Arrays. + # linear rows are sequentially-packed first (inner loop), + # columns next (outer loop): + # 0 1 2 3 + # 4 5 6 7 + # 8 9 10 11 + # => + # 0 1 2 3 4 .... 10 11 + xf = reduce(operator.add, X) + yf = reduce(operator.add, Y) + print ("flattened X,Y") + print ("\t", xf) + print ("\t", yf) + # and create a linear result2, same scheme + result2 = [0] * (ydim1*xdim2) + + ######## + # now create the schedule. we use three generators, zipped + # together + + class SVSHAPE: + pass + # result uses SVSHAPE0 + SVSHAPE0 = SVSHAPE() + SVSHAPE0.lims = [ydim2, xdim2, 1] + SVSHAPE0.order = [0,2,1] # result iterates through i and j (modulo) + SVSHAPE0.mode = 0b00 + SVSHAPE0.offset = 0 # no offset + SVSHAPE0.invxyz = [0,0,0] # no inversion + # X uses SVSHAPE1 + SVSHAPE1 = SVSHAPE() + SVSHAPE1.lims = [ydim2, xdim2, ydim1] + SVSHAPE1.order = [1,2,0] # X iterates through i and k + SVSHAPE1.mode = 0b10 + SVSHAPE1.offset = 0 # no offset + SVSHAPE1.invxyz = [0,0,0] # no inversion + # y-selector uses SHAPE2 + SVSHAPE2 = SVSHAPE() + SVSHAPE2.lims = [ydim2, xdim2, ydim1] + SVSHAPE2.order = [1,2,0] # Y iterates through k and j + SVSHAPE2.mode = 0b01 + SVSHAPE2.offset = 0 # no offset + SVSHAPE2.invxyz = [0,0,0] # no inversion + + # perform the iteration over the *linear* arrays using the + # schedules + VL = ydim2 * xdim2 * ydim1 + i = 0 + for i, idxs in enumerate(iterate_triple(SVSHAPE0, SVSHAPE1, SVSHAPE2)): + if i == VL: + break + print ("idxs", idxs, len(result2), len(xf), len(yf)) + r_idx, x_idx, y_idx = idxs + result2[r_idx] += xf[x_idx] * yf[y_idx] + + # now print out sections of result array, assuming elements of a "row" + # are in sequence (inner loop), columns are outer + for i in range(0, len(result2), xdim2): + print ("\t", result2[i:i+xdim2]) if __name__ == '__main__': matrix_demo() diff --git a/openpower/sv/remapyield.py b/openpower/sv/remapyield.py index 4cca1f39a..ac3217b84 100644 --- a/openpower/sv/remapyield.py +++ b/openpower/sv/remapyield.py @@ -27,7 +27,22 @@ def iterate_indices(SVSHAPE): skip += 1 continue # construct the (up to) 3D remap schedule - yield (x + y * xd + z * xd * yd) + if SVSHAPE.mode == 0b00: + result = z + result += y * zd + result += x * zd * yd + elif SVSHAPE.mode == 0b01: + result = z + result += x * zd + #result = z + #result = result * xd + x + #result = result * yd + y + elif SVSHAPE.mode == 0b10: + result = x + result += y * xd + #result += z * xd * yd + + yield result def demo(): # set the dimension sizes here @@ -43,10 +58,10 @@ def demo(): pass SVSHAPE0 = SVSHAPE() SVSHAPE0.lims = [xdim, ydim, zdim] - SVSHAPE0.idxs = [0,0,0] # starting indices SVSHAPE0.order = [1,0,2] # experiment with different permutations, here + SVSHAPE0.mode = 0b00 SVSHAPE0.offset = 0 # experiment with different offset, here - SVSHAPE0.invxyz = [0,1,0] # inversion if desired + SVSHAPE0.invxyz = [0,0,0] # inversion if desired # enumerate over the iterator function, getting new indices for idx, new_idx in enumerate(iterate_indices(SVSHAPE0)): diff --git a/openpower/sv/shape_table_format.mdwn b/openpower/sv/shape_table_format.mdwn index 417dcc893..082c8e301 100644 --- a/openpower/sv/shape_table_format.mdwn +++ b/openpower/sv/shape_table_format.mdwn @@ -7,9 +7,9 @@ disabled: the register's elements are a linear (1D) vector. mode sets different behaviours (straight matrix multiply, FFT, DCT). -* **mode=0b00** sets matrix multiply -* **mode=0b01** sets FFT -* **mode=0b10** is reserved +* **mode=0b00** sets straight permute +* **mode=0b01** sets "skip 2nd dimension" +* **mode=0b10** sets "skip 1st dimension" * **mode=0b11** is reserved invxyz will invert the start index of each of x, y or z. If invxyz[0] is