heat.tiling
Tiling functions/classes. With these classes, you can classes you can address blocks of data in a DNDarray
Module Contents
- class SplitTiles(arr: heat.core.dndarray.DNDarray)
Initialize tiles with the tile divisions equal to the theoretical split dimensions in every dimension
- Parameters:
arr (DNDarray) – Base array for which to create the tiles
- Variables:
__DNDarray (DNDarray) – the
DNDarray
associated with the tiles__lshape_map (torch.Tensor) – map of the shapes of the local torch tensors of arr
__tile_locations (torch.Tensor) – locations of the tiles of
arr
__tile_ends_g (torch.Tensor) – the global indices of the ends of the tiles
__tile_dims (torch.Tensor) – the dimensions of all of the tiles
Examples
>>> a = ht.zeros((10, 11,), split=None) >>> a.create_split_tiles() >>> print(a.tiles.tile_ends_g) [0/2] tensor([[ 4, 7, 10], [0/2] [ 4, 8, 11]], dtype=torch.int32) [1/2] tensor([[ 4, 7, 10], [1/2] [ 4, 8, 11]], dtype=torch.int32) [2/2] tensor([[ 4, 7, 10], [2/2] [ 4, 8, 11]], dtype=torch.int32) >>> print(a.tiles.tile_locations) [0/2] tensor([[0, 0, 0], [0/2] [0, 0, 0], [0/2] [0, 0, 0]], dtype=torch.int32) [1/2] tensor([[1, 1, 1], [1/2] [1, 1, 1], [1/2] [1, 1, 1]], dtype=torch.int32) [2/2] tensor([[2, 2, 2], [2/2] [2, 2, 2], [2/2] [2, 2, 2]], dtype=torch.int32) >>> a = ht.zeros((10, 11), split=1) >>> a.create_split_tiles() >>> print(a.tiles.tile_ends_g) [0/2] tensor([[ 4, 7, 10], [0/2] [ 4, 8, 11]], dtype=torch.int32) [1/2] tensor([[ 4, 7, 10], [1/2] [ 4, 8, 11]], dtype=torch.int32) [2/2] tensor([[ 4, 7, 10], [2/2] [ 4, 8, 11]], dtype=torch.int32) >>> print(a.tiles.tile_locations) [0/2] tensor([[0, 1, 2], [0/2] [0, 1, 2], [0/2] [0, 1, 2]], dtype=torch.int32) [1/2] tensor([[0, 1, 2], [1/2] [0, 1, 2], [1/2] [0, 1, 2]], dtype=torch.int32) [2/2] tensor([[0, 1, 2], [2/2] [0, 1, 2], [2/2] [0, 1, 2]], dtype=torch.int32)
- set_tile_locations(split: int, tile_dims: torch.Tensor, arr: heat.core.dndarray.DNDarray) torch.Tensor
Create a torch.Tensor which contains the locations of the tiles of
arr
for the given split- Parameters:
split (int) – Target split dimension. Does not need to be equal to
arr.split
tile_dims (torch.Tensor) – Tensor containing the sizes of the each tile
arr (DNDarray) – Array for which the tiles are being created for
- __getitem__(key: int | slice | Tuple[int | slice, Ellipsis]) torch.Tensor
Getitem function for getting tiles. Returns the tile which is specified is returned, but only on the process which it resides
- Parameters:
key (int or Tuple or Slice) – Key which identifies the tile/s to get
Examples
>>> test = torch.arange(np.prod([i + 6 for i in range(2)])).reshape([i + 6 for i in range(2)]) >>> a = ht.array(test, split=0).larray [0/2] tensor([[ 0., 1., 2., 3., 4., 5., 6.], [0/2] [ 7., 8., 9., 10., 11., 12., 13.]]) [1/2] tensor([[14., 15., 16., 17., 18., 19., 20.], [1/2] [21., 22., 23., 24., 25., 26., 27.]]) [2/2] tensor([[28., 29., 30., 31., 32., 33., 34.], [2/2] [35., 36., 37., 38., 39., 40., 41.]]) >>> a.create_split_tiles() >>> a.tiles[:2, 2] [0/2] tensor([[ 5., 6.], [0/2] [12., 13.]]) [1/2] tensor([[19., 20.], [1/2] [26., 27.]]) [2/2] None >>> a = ht.array(test, split=1) >>> a.create_split_tiles() >>> a.tiles[1] [0/2] tensor([[14., 15., 16.], [0/2] [21., 22., 23.]]) [1/2] tensor([[17., 18.], [1/2] [24., 25.]]) [2/2] tensor([[19., 20.], [2/2] [26., 27.]])
- __get_tile_slices(key: int | slice | Tuple[int | slice, Ellipsis]) Tuple[slice, Ellipsis]
Create and return slices to convert a key from the tile indices to the normal indices
- get_tile_size(key: int | slice | Tuple[int | slice, Ellipsis]) Tuple[int, Ellipsis]
Get the size of a tile or tiles indicated by the given key
- Parameters:
key (int or slice or tuple) – which tiles to get
- __setitem__(key: int | slice | Tuple[int | slice, Ellipsis], value: int | float | torch.Tensor) None
Set the values of a tile
- Parameters:
key (int or Tuple or Slice) – Key which identifies the tile/s to get
value (int or torch.Tensor) – Value to be set on the tile
Examples
see getitem function for this class
- class SquareDiagTiles(arr: heat.core.dndarray.DNDarray, tiles_per_proc: int = 2)
Generate the tile map and the other objects which may be useful. The tiles generated here are based of square tiles along the diagonal. The size of these tiles along the diagonal dictate the divisions across all processes. If
gshape[0]>>gshape[1]
then there will be extra tiles generated below the diagonal. Ifgshape[0]
is close togshape[1]
, then the last tile (as well as the other tiles which correspond with said tile) will be extended to cover the whole array. However, extra tiles are not generated above the diagonal in the case thatgshape[0]<<gshape[1]
.- Parameters:
arr (DNDarray) – The array to be tiled
tiles_per_proc (int, optional) – The number of divisions per process Default: 2
- Variables:
__col_per_proc_list (List) – List is length of the number of processes, each element has the number of tile columns on the process whos rank equals the index
__DNDarray (DNDarray) – The whole DNDarray
__lshape_map (torch.Tensor) –
unit -> [rank, row size, column size]
Tensor filled with the shapes of the local tensors__tile_map (torch.Tensor) –
units -> row, column, start index in each direction, process
Tensor filled with the global indices of the generated tiles__row_per_proc_list (List) – List is length of the number of processes, each element has the number of tile rows on the process whos rank equals the index
Warning
The generation of these tiles may unbalance the original
DNDarray
!Notes
This tiling scheme is intended for use with the
qr()
function.- __adjust_cols_sp1_m_ls_n(arr: heat.core.dndarray.DNDarray, col_per_proc_list: List[int, Ellipsis], last_diag_pr: int, col_inds: List[int, Ellipsis], lshape_map: torch.Tensor) None
Add more columns after the diagonal ends if
m<n
andarr.split==1
- __adjust_last_row_sp0_m_ge_n(arr: heat.core.dndarray.DNDarray, lshape_map: torch.Tensor, last_diag_pr: int, row_inds: List[int, Ellipsis], row_per_proc_list: List[int, Ellipsis], tile_columns: int) None
Need to adjust the size of last row if
arr.split==0
and the diagonal ends before the last tile. This should only be run ifarr,split==0
andlast_diag_pr<arr.comm.size-1
.
- __adjust_lshape_sp0_1tile(arr: heat.core.dndarray.DNDarray, col_inds: List[int, Ellipsis], lshape_map: torch.Tensor, tiles_per_proc: int) None
If the split is 0 and the number of tiles per proc is 1 then the local data may need to be redistributed to fit the full diagonal on as many processes as possible. If there is a process where there is only 1 element, this function will adjust the
lshape_map
then redistributearr
so that there is not a single diagonal element on one process
- __create_cols(arr: heat.core.dndarray.DNDarray, lshape_map: torch.Tensor, tiles_per_proc: int) Tuple[torch.Tensor, List[int, Ellipsis], List[int, Ellipsis], torch.Tensor]
Calculates the last diagonal process, then creates a list of the number of tile columns per process, then calculates the starting indices of the columns. Also returns the number of tile columns.
- Parameters:
arr (DNDarray) – DNDarray for which to find the tile columns for
lshape_map (torch.Tensor) – The map of the local shapes (for more info see:
create_lshape_map()
)tiles_per_proc (int) – The number of divisions per process
- __def_end_row_inds_sp0_m_ge_n(arr: heat.core.dndarray.DNDarray, row_inds: List[int, Ellipsis], last_diag_pr: int, tiles_per_proc: int, lshape_map: torch.Tensor) None
Adjust the rows on the processes which are greater than the last diagonal processs to have rows which are chunked evenly into
tiles_per_proc
rows.
- __last_tile_row_adjust_sp1(arr: heat.core.dndarray.DNDarray, row_inds: List[int, Ellipsis]) None
Add extra row/s if there is space below the diagonal (
split=1
)
- get_start_stop(key: int | slice | Tuple[int, slice, Ellipsis]) Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]
Returns the start and stop indices in form of
(dim0 start, dim0 stop, dim1 start, dim1 stop)
which correspond to the tile/s which corresponds to the given key. The key MUST use global indices.- Parameters:
key (int or Tuple or List or slice) – Indices to select the tile STRIDES ARE NOT ALLOWED, MUST BE GLOBAL INDICES
Examples
>>> a = ht.zeros((12, 10), split=0) >>> a_tiles = ht.tiling.SquareDiagTiles(a, tiles_per_proc=2) # type: tiling.SquareDiagTiles >>> print(a_tiles.get_start_stop(key=(slice(0, 2), 2))) [0/1] (tensor(0), tensor(6), tensor(6), tensor(8)) [1/1] (tensor(0), tensor(6), tensor(6), tensor(8)) >>> print(a_tiles.get_start_stop(key=(0, 2))) [0/1] (tensor(0), tensor(3), tensor(6), tensor(8)) [1/1] (tensor(0), tensor(3), tensor(6), tensor(8)) >>> print(a_tiles.get_start_stop(key=2)) [0/1] (tensor(0), tensor(2), tensor(0), tensor(10)) [1/1] (tensor(0), tensor(2), tensor(0), tensor(10)) >>> print(a_tiles.get_start_stop(key=(3, 3))) [0/1] (tensor(2), tensor(6), tensor(8), tensor(10)) [1/1] (tensor(2), tensor(6), tensor(8), tensor(10))
- __getitem__(key: int | slice | Tuple[int, slice, Ellipsis]) torch.Tensor
Returns a local selection of the DNDarray corresponding to the tile/s desired Standard getitem function for the tiles. The returned item is a view of the original DNDarray, operations which are done to this view will change the original array. STRIDES ARE NOT AVAILABLE, NOR ARE CROSS-SPLIT SLICES
- Parameters:
key (int, slice, tuple) – indices of the tile/s desired
Examples
>>> a = ht.zeros((12, 10), split=0) >>> a_tiles = tiling.SquareDiagTiles(a, tiles_per_proc=2) # type: tiling.SquareDiagTiles >>> print(a_tiles[2, 3]) [0/1] None [1/1] tensor([[0., 0.], [1/1] [0., 0.]]) >>> print(a_tiles[2]) [0/1] None [1/1] tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [1/1] [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) >>> print(a_tiles[0:2, 1]) [0/1] tensor([[0., 0., 0.], [0/1] [0., 0., 0.], [0/1] [0., 0., 0.], [0/1] [0., 0., 0.], [0/1] [0., 0., 0.], [0/1] [0., 0., 0.]]) [1/1] None
- local_get(key: int | slice | Tuple[int, slice, Ellipsis]) torch.Tensor
Returns the local tile/s corresponding to the key given Getitem routing using local indices, converts to global indices then uses getitem
- Parameters:
key (int, slice, tuple, list) – Indices of the tile/s desired. If the stop index of a slice is larger than the end will be adjusted to the maximum allowed
Examples
See local_set function.
- local_set(key: int | slice | Tuple[int, slice, Ellipsis], value: int | float | torch.Tensor)
Setitem routing to set data to a local tile (using local indices)
- Parameters:
key (int or slice or Tuple[int,...]) – Indices of the tile/s desired If the stop index of a slice is larger than the end will be adjusted to the maximum allowed
value (torch.Tensor or int or float) – Data to be written to the tile
Examples
>>> a = ht.zeros((11, 10), split=0) >>> a_tiles = tiling.SquareDiagTiles(a, tiles_per_proc=2) # type: tiling.SquareDiagTiles >>> local = a_tiles.local_get(key=slice(None)) >>> a_tiles.local_set(key=slice(None), value=torch.arange(local.numel()).reshape(local.shape)) >>> print(a.larray) [0/1] tensor([[ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.], [0/1] [10., 11., 12., 13., 14., 15., 16., 17., 18., 19.], [0/1] [20., 21., 22., 23., 24., 25., 26., 27., 28., 29.], [0/1] [30., 31., 32., 33., 34., 35., 36., 37., 38., 39.], [0/1] [40., 41., 42., 43., 44., 45., 46., 47., 48., 49.], [0/1] [50., 51., 52., 53., 54., 55., 56., 57., 58., 59.]]) [1/1] tensor([[ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.], [1/1] [10., 11., 12., 13., 14., 15., 16., 17., 18., 19.], [1/1] [20., 21., 22., 23., 24., 25., 26., 27., 28., 29.], [1/1] [30., 31., 32., 33., 34., 35., 36., 37., 38., 39.], [1/1] [40., 41., 42., 43., 44., 45., 46., 47., 48., 49.]]) >>> a.lloc[:] = 0 >>> a_tiles.local_set(key=(0, 2), value=10) [0/1] tensor([[ 0., 0., 0., 0., 0., 0., 10., 10., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 10., 10., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 10., 10., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) [1/1] tensor([[ 0., 0., 0., 0., 0., 0., 10., 10., 0., 0.], [1/1] [ 0., 0., 0., 0., 0., 0., 10., 10., 0., 0.], [1/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [1/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [1/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]) >>> a_tiles.local_set(key=(slice(None), 1), value=10) [0/1] tensor([[ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [0/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [0/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [0/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [0/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [0/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.]]) [1/1] tensor([[ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [1/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [1/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [1/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.], [1/1] [ 0., 0., 0., 10., 10., 10., 0., 0., 0., 0.]])
- local_to_global(key: int | slice | Tuple[int, slice, Ellipsis], rank: int) Tuple[int, slice, Ellipsis]
Convert local indices to global indices
- Parameters:
key (int or slice or Tuple or List) – Indices of the tile/s desired. If the stop index of a slice is larger than the end will be adjusted to the maximum allowed
rank (int) – Process rank
Examples
>>> a = ht.zeros((11, 10), split=0) >>> a_tiles = tiling.SquareDiagTiles(a, tiles_per_proc=2) # type: tiling.SquareDiagTiles >>> rank = a.comm.rank >>> print(a_tiles.local_to_global(key=(slice(None), 1), rank=rank)) [0/1] (slice(0, 2, None), 1) [1/1] (slice(2, 4, None), 1) >>> print(a_tiles.local_to_global(key=(0, 2), rank=0)) [0/1] (0, 2) [1/1] (0, 2) >>> print(a_tiles.local_to_global(key=(0, 2), rank=1)) [0/1] (2, 2) [1/1] (2, 2)
- match_tiles(tiles_to_match: SquareDiagTiles) None
Function to match the tile sizes of another tile map
- Parameters:
tiles_to_match (SquareDiagTiles) – The tiles which should be matched by the current tiling scheme
Notes
This function overwrites most, if not all, of the elements of this class. Intended for use with the Q matrix, to match the tiling of a/R. For this to work properly it is required that the 0th dim of both matrices is equal
- __setitem__(key: int | slice | Tuple[int, slice, Ellipsis], value: int | float | torch.Tensor) None
Item setter, uses the torch item setter and the getitem routines to set the values of the original array (arr in __init__)
- Parameters:
key (int or slice or Tuple[int,...]) – Tile indices to identify the target tiles
value (int or torch.Tensor) – Values to be set
Example
>>> a = ht.zeros((12, 10), split=0) >>> a_tiles = tiling.SquareDiagTiles(a, tiles_per_proc=2) # type: tiling.SquareDiagTiles >>> a_tiles[0:2, 2] = 11 >>> a_tiles[0, 0] = 22 >>> a_tiles[2] = 33 >>> a_tiles[3, 3] = 44 >>> print(a.larray) [0/1] tensor([[22., 22., 22., 0., 0., 0., 11., 11., 0., 0.], [0/1] [22., 22., 22., 0., 0., 0., 11., 11., 0., 0.], [0/1] [22., 22., 22., 0., 0., 0., 11., 11., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 11., 11., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 11., 11., 0., 0.], [0/1] [ 0., 0., 0., 0., 0., 0., 11., 11., 0., 0.]]) [1/1] tensor([[33., 33., 33., 33., 33., 33., 33., 33., 33., 33.], [1/1] [33., 33., 33., 33., 33., 33., 33., 33., 33., 33.], [1/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 44., 44.], [1/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 44., 44.], [1/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 44., 44.], [1/1] [ 0., 0., 0., 0., 0., 0., 0., 0., 44., 44.]])