Ejemplo n.º 1
0
 def _sample_basic(self, rfunc_name, shape, block_shape, dtype,
                   rfunc_args) -> BlockArray:
     if shape is None:
         assert block_shape is None
         shape = ()
         block_shape = ()
     else:
         assert block_shape is not None
     if dtype is None:
         dtype = np.float64
     assert isinstance(dtype, type)
     grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype=dtype.__name__)
     ba: BlockArray = BlockArray(grid, self._system)
     for grid_entry in ba.grid.get_entry_iterator():
         rng_params = list(self._rng.new_block_rng_params())
         # Size and dtype to begin with.
         this_block_shape = grid.get_block_shape(grid_entry)
         size = int(np.product(this_block_shape))
         # Inconsistent param orderings.
         if rfunc_name == "random":
             rfunc_args_final = tuple([size] + list(rfunc_args))
         elif rfunc_name == "integers":
             # rfunc_args == (low, high, dtype, endpoint)
             rfunc_args_final = tuple(
                 list(rfunc_args[:2]) + [size] + list(rfunc_args[2:]))
         else:
             rfunc_args_final = tuple(list(rfunc_args) + [size])
         block: Block = ba.blocks[grid_entry]
         block.oid = self._system.random_block(rng_params,
                                               rfunc_name,
                                               rfunc_args_final,
                                               this_block_shape,
                                               dtype,
                                               syskwargs={
                                                   "grid_entry": grid_entry,
                                                   "grid_shape":
                                                   grid.grid_shape
                                               })
     return ba
Ejemplo n.º 2
0
    def swapaxes(self, axis1, axis2):
        meta_swap = self.grid.to_meta()
        shape = list(meta_swap["shape"])
        block_shape = list(meta_swap["block_shape"])
        dim = len(shape)
        if axis1 >= dim or axis2 >= dim:
            raise ValueError("axis is larger than the array dimension")
        shape[axis1], shape[axis2] = shape[axis2], shape[axis1]
        block_shape[axis1], block_shape[axis2] = block_shape[
            axis2], block_shape[axis1]
        meta_swap["shape"] = tuple(shape)
        meta_swap["block_shape"] = tuple(block_shape)
        grid_swap = ArrayGrid.from_meta(meta_swap)
        rarr_src = np.ndarray(self.blocks.shape, dtype='O')

        for grid_entry in self.grid.get_entry_iterator():
            rarr_src[grid_entry] = self.blocks[grid_entry].swapaxes(
                axis1, axis2)
        rarr_src = rarr_src.swapaxes(axis1, axis2)

        rarr_swap = BlockArray(grid_swap, self.system, rarr_src)
        return rarr_swap
Ejemplo n.º 3
0
    def __init__(self,
                 source,
                 sel: BasicSelection = None,
                 block_shape: tuple = None):
        self._source: BlockArrayBase = source
        self._system: System = self._source.system

        if sel is None:
            sel = BasicSelection.from_shape(self._source.shape)
        # Currently, this is all we support.
        assert len(sel.axes) == len(self._source.shape)
        self.sel = sel

        self.shape: tuple = self.sel.get_output_shape()
        if block_shape is None:
            block_shape: tuple = array_utils.block_shape_from_subscript(
                self.sel.selector(), self._source.block_shape)
        self.block_shape = block_shape
        assert len(self.block_shape) == len(self.shape)
        self.grid: ArrayGrid = ArrayGrid(self.shape,
                                         self.block_shape,
                                         dtype=self._source.dtype.__name__)
Ejemplo n.º 4
0
 def _broadcast_bop(self, op_name, arr_1, arr_2) -> BlockArray:
     """
     We want to avoid invoking this op whenever possible; NumPy's imp is faster.
     :param op_name: Name of binary operation.
     :param arr_1: A BlockArray.
     :param arr_2: A BlockArray.
     :return: A BlockArray.
     """
     if arr_1.shape != arr_2.shape:
         output_grid_shape = array_utils.broadcast_shape(
             arr_1.grid.grid_shape, arr_2.grid.grid_shape)
         arr_1 = arr_1.broadcast_to(output_grid_shape)
         arr_2 = arr_2.broadcast_to(output_grid_shape)
     dtype = array_utils.get_bop_output_type(op_name, arr_1.dtype,
                                             arr_2.dtype)
     grid = ArrayGrid(arr_1.shape, arr_1.block_shape, dtype.__name__)
     rarr = BlockArray(grid, self.system)
     for grid_entry in rarr.grid.get_entry_iterator():
         block_1: Block = arr_1.blocks[grid_entry]
         block_2: Block = arr_2.blocks[grid_entry]
         rarr.blocks[grid_entry] = block_1.bop(op_name, block_2, {})
     return rarr
Ejemplo n.º 5
0
 def diag(self, X: BlockArray) -> BlockArray:
     if len(X.shape) == 1:
         shape = X.shape[0], X.shape[0]
         block_shape = X.block_shape[0], X.block_shape[0]
         grid = ArrayGrid(shape, block_shape, X.dtype.__name__)
         grid_meta = grid.to_meta()
         rarr = BlockArray(grid, self.system)
         for grid_entry in grid.get_entry_iterator():
             syskwargs = {
                 "grid_entry": grid_entry,
                 "grid_shape": grid.grid_shape
             }
             if np.all(np.diff(grid_entry) == 0):
                 # This is a diagonal block.
                 rarr.blocks[grid_entry].oid = self.system.diag(
                     X.blocks[grid_entry[0]].oid, syskwargs=syskwargs)
             else:
                 rarr.blocks[grid_entry].oid = self.system.new_block(
                     "zeros", grid_entry, grid_meta, syskwargs=syskwargs)
     elif len(X.shape) == 2:
         assert X.shape[0] == X.shape[1]
         assert X.block_shape[0] == X.block_shape[1]
         shape = X.shape[0],
         block_shape = X.block_shape[0],
         grid = ArrayGrid(shape, block_shape, X.dtype.__name__)
         rarr = BlockArray(grid, self.system)
         for grid_entry in X.grid.get_entry_iterator():
             out_grid_entry = grid_entry[:1]
             out_grid_shape = grid.grid_shape[:1]
             syskwargs = {
                 "grid_entry": out_grid_entry,
                 "grid_shape": out_grid_shape
             }
             if np.all(np.diff(grid_entry) == 0):
                 # This is a diagonal block.
                 rarr.blocks[out_grid_entry].oid = self.system.diag(
                     X.blocks[grid_entry].oid, syskwargs=syskwargs)
     else:
         raise ValueError("X must have 1 or 2 axes.")
     return rarr
Ejemplo n.º 6
0
def delete_block_s3(filename: AnyStr, grid_entry: Tuple, grid_meta: Dict):
    return np.array(StoredArrayS3(
        filename, ArrayGrid.from_meta(grid_meta)).delete(grid_entry),
                    dtype=dict)
Ejemplo n.º 7
0
def read_block_s3(filename: AnyStr, grid_entry: Tuple, grid_meta: Dict):
    return StoredArrayS3(filename,
                         ArrayGrid.from_meta(grid_meta)).get(grid_entry)
Ejemplo n.º 8
0
def write_block_s3(block: Any, filename: AnyStr, grid_entry: Tuple,
                   grid_meta: Dict):
    return np.array(StoredArrayS3(filename,
                                  ArrayGrid.from_meta(grid_meta)).put(
                                      grid_entry, block),
                    dtype=dict)
Ejemplo n.º 9
0
 def loadtxt(self,
             fname,
             dtype=float,
             comments='# ',
             delimiter=' ',
             converters=None,
             skiprows=0,
             usecols=None,
             unpack=False,
             ndmin=0,
             encoding='bytes',
             max_rows=None,
             num_workers=4) -> BlockArray:
     # pylint: disable=unused-variable
     bytes_per_char, bytes_per_row, bytes_per_col, num_cols = storage_utils.get_np_txt_info(
         fname, comments, delimiter)
     chars_per_row = bytes_per_row // bytes_per_char
     assert np.allclose(float(chars_per_row),
                        bytes_per_row / bytes_per_char)
     comment_lines, trailing_newlines = storage_utils.get_np_comments(
         fname, comments)
     nonrow_chars = trailing_newlines
     for line in comment_lines:
         nonrow_chars += len(line)
     file_size = storage_utils.get_file_size(fname)
     file_chars = file_size // bytes_per_char
     assert np.allclose(float(file_chars), file_size / bytes_per_char)
     row_chars = file_chars - nonrow_chars
     num_rows = row_chars // chars_per_row
     assert np.allclose(float(num_rows), float(row_chars / chars_per_row))
     num_rows_final = num_rows - skiprows
     if max_rows is not None:
         num_rows_final = (num_rows_final, max_rows)
     row_batches: storage_utils.Batch = storage_utils.Batch.from_num_batches(
         num_rows_final, num_workers)
     grid = ArrayGrid(
         shape=(num_rows_final, num_cols),
         block_shape=(row_batches.batch_size, num_cols),
         dtype=np.float64.__name__ if dtype is float else dtype.__name__)
     result: BlockArray = BlockArray(grid, system=self.system)
     for i, grid_entry in enumerate(grid.get_entry_iterator()):
         row_start, row_end = row_batches.batches[i]
         batch_skiprows = skiprows + row_start + 1
         batch_max_rows = grid.get_block_shape(grid_entry)[0]
         assert batch_max_rows == row_end - row_start
         result.blocks[grid_entry].oid = self.loadtxt_block(
             fname,
             dtype=dtype,
             comments=comments,
             delimiter=delimiter,
             converters=converters,
             skiprows=batch_skiprows,
             usecols=usecols,
             unpack=unpack,
             ndmin=ndmin,
             encoding=encoding,
             max_rows=batch_max_rows,
             syskwargs={
                 "grid_entry": grid_entry,
                 "grid_shape": grid.grid_shape
             })
     return result
Ejemplo n.º 10
0
def write_meta_s3(filename: AnyStr, grid_meta: Dict):
    sa: StoredArrayS3 = StoredArrayS3(filename, ArrayGrid.from_meta(grid_meta))
    return np.array(sa.put_grid(sa.grid), dtype=dict)
Ejemplo n.º 11
0
 def astype(self, dtype):
     grid = ArrayGrid(self.shape, self.block_shape, dtype.__name__)
     result = BlockArray(grid, self.system)
     for grid_entry in result.grid.get_entry_iterator():
         result.blocks[grid_entry] = self.blocks[grid_entry].astype(dtype)
     return result
Ejemplo n.º 12
0
    def reduce_axis(self, op_name, axis, keepdims=False):
        if not (axis is None or isinstance(axis, (int, np.int32, np.int64))):
            raise NotImplementedError("Only integer axis is currently supported.")
        result_blocks = np.empty_like(self.blocks, dtype=Block)
        for grid_entry in self.grid.get_entry_iterator():
            result_blocks[grid_entry] = self.blocks[grid_entry].reduce_axis(op_name,
                                                                            axis,
                                                                            keepdims=keepdims)
        result_shape = []
        result_block_shape = []
        for curr_axis in range(len(self.shape)):
            axis_size, axis_block_size = self.shape[curr_axis], self.block_shape[curr_axis]
            if curr_axis == axis or axis is None:
                if keepdims:
                    axis_size, axis_block_size = 1, 1
                else:
                    continue
            result_shape.append(axis_size)
            result_block_shape.append(axis_block_size)
        result_shape = tuple(result_shape)
        result_block_shape = tuple(result_block_shape)
        result_dtype = array_utils.get_reduce_output_type(op_name, self.dtype)
        result_grid = ArrayGrid(shape=result_shape,
                                block_shape=result_block_shape,
                                dtype=result_dtype.__name__)
        result = BlockArray(result_grid, self.system)

        if op_name in settings.np_pairwise_reduction_map:
            # Do a pairwise reduction with the pairwise reduction op.
            pairwise_op_name = settings.np_pairwise_reduction_map.get(op_name, op_name)
            if axis is None:
                reduced_block: Block = None
                for grid_entry in self.grid.get_entry_iterator():
                    if reduced_block is None:
                        reduced_block = result_blocks[grid_entry]
                        continue
                    next_block = result_blocks[grid_entry]
                    reduced_block = reduced_block.bop(pairwise_op_name, next_block, {})
                if result.shape == ():
                    result.blocks[()] = reduced_block
                else:
                    result.blocks[:] = reduced_block

            else:
                for result_grid_entry in result_grid.get_entry_iterator():
                    reduced_block: Block = None
                    for sum_dim in range(self.grid.grid_shape[axis]):
                        grid_entry = list(result_grid_entry)
                        if keepdims:
                            grid_entry[axis] = sum_dim
                        else:
                            grid_entry = grid_entry[:axis] + [sum_dim] + grid_entry[axis:]
                        grid_entry = tuple(grid_entry)
                        next_block: Block = result_blocks[grid_entry]
                        if reduced_block is None:
                            reduced_block = next_block
                        else:
                            reduced_block = reduced_block.bop(pairwise_op_name, next_block, {})
                    result.blocks[result_grid_entry] = reduced_block
        else:
            op_func = np.__getattribute__(op_name)
            if result.shape == ():
                result.blocks[()] = op_func(result_blocks, axis=axis, keepdims=keepdims)
            else:
                result.blocks = op_func(result_blocks, axis=axis, keepdims=keepdims)
        return result
Ejemplo n.º 13
0
    def reshape(self, shape=None, block_shape=None):
        # TODO (hme): Add support for arbitrary reshape.
        if shape is None:
            shape = self.shape
        if block_shape is None:
            block_shape = self.block_shape
        if shape == self.shape and block_shape == self.block_shape:
            return self

        temp_shape = shape
        temp_block_shape = block_shape
        shape = []
        block_shape = []
        negative_one = False
        for i, dim in enumerate(temp_shape):
            if dim == -1:
                assert len(self.shape) == 1
                if negative_one:
                    raise Exception("Only one -1 permitted in reshape.")
                negative_one = True
                shape.append(self.shape[i])
                assert temp_block_shape[i] == -1
                block_shape.append(self.block_shape[0])
            else:
                shape.append(dim)
                block_shape.append(temp_block_shape[i])
        del temp_shape
        shape = tuple(shape)
        block_shape = tuple(block_shape)

        assert np.product(shape) == np.product(self.shape)
        # Make sure the difference is either a preceding or succeeding one.
        if len(shape) > len(self.shape):
            if shape[0] == 1:
                grid_entry_op = "shift"
                assert shape[1:] == self.shape
            elif shape[-1] == 1:
                grid_entry_op = "pop"
                assert shape[:-1] == self.shape
            else:
                raise Exception()
        elif len(shape) < len(self.shape):
            if self.shape[0] == 1:
                grid_entry_op = "prep"
                assert self.shape[1:] == shape
            elif self.shape[-1] == 1:
                grid_entry_op = "app"
                assert self.shape[:-1] == shape
            else:
                raise Exception()
        else:
            grid_entry_op = "none"
            assert self.shape == shape

        grid = ArrayGrid(shape=shape,
                         block_shape=block_shape,
                         dtype=self.grid.dtype.__name__)
        grid_meta = grid.to_meta()
        rarr = BlockArray(grid, self.system)
        for grid_entry in grid.get_entry_iterator():
            rarr.blocks[grid_entry].oid = self.system.empty(grid_entry, grid_meta,
                                                            syskwargs={
                                                                "grid_entry": grid_entry,
                                                                "grid_shape": grid.grid_shape
                                                            })
            grid_entry_slice = grid.get_slice(grid_entry)
            if grid_entry_op == "shift":
                grid_entry_slice = tuple([0] + list(grid_entry_slice)[1:])
                self_grid_entry_slice = self.grid.get_slice(grid_entry[1:])
            elif grid_entry_op == "pop":
                grid_entry_slice = tuple(list(grid_entry_slice)[:-1] + [0])
                self_grid_entry_slice = self.grid.get_slice(grid_entry[:-1])
            elif grid_entry_op == "prep":
                self_grid_entry_slice = self.grid.get_slice(tuple([0] + list(grid_entry)))
            elif grid_entry_op == "prep":
                self_grid_entry_slice = self.grid.get_slice(tuple(list(grid_entry) + [0]))
            else:
                assert grid_entry_op == "none"
                self_grid_entry_slice = grid_entry_slice

            # TODO (hme): This is costly.
            rarr[grid_entry_slice] = self[self_grid_entry_slice]
        return rarr
Ejemplo n.º 14
0
 def empty(self, grid_entry, grid_meta):
     grid = ArrayGrid.from_meta(grid_meta)
     block_shape = grid.get_block_shape(grid_entry)
     return np.empty(block_shape, dtype=grid.dtype)
Ejemplo n.º 15
0
def test_block_shape(nps_app_inst):
    app = nps_app_inst
    dtype = np.float64
    shape = (10**9, 250)
    cluster_shape = (1, 1)
    num_cores = 64
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          cluster_shape=cluster_shape,
                                          num_cores=num_cores)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape == (num_cores, 1)

    cluster_shape = (16, 1)
    num_cores = 64 * np.product(cluster_shape)
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          cluster_shape=cluster_shape,
                                          num_cores=num_cores)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape == (num_cores, 1)

    shape = (250, 10**9)
    cluster_shape = (1, 16)
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          cluster_shape=cluster_shape,
                                          num_cores=num_cores)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape == (1, num_cores)

    shape = (10**4, 10**4)
    cluster_shape = (1, 1)
    num_cores = 64
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          cluster_shape=cluster_shape,
                                          num_cores=num_cores)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape == (int(num_cores**.5), int(num_cores**.5))

    shape = (10**4, 10**4 // dtype(0).nbytes)
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          cluster_shape=cluster_shape,
                                          num_cores=num_cores)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape != (1, 1)

    shape = (10**4, 10**4 // dtype(0).nbytes - 1)
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          cluster_shape=cluster_shape,
                                          num_cores=num_cores)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape == (1, 1)

    shape = (10**4, 10**4)
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          num_cores=num_cores)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape == (int(num_cores**.5), int(num_cores**.5))

    cluster_shape = (12, 1)
    num_cores = systems_utils.get_num_cores()
    block_shape = app.compute_block_shape(shape=shape,
                                          dtype=dtype,
                                          cluster_shape=cluster_shape)
    grid: ArrayGrid = ArrayGrid(shape, block_shape, dtype.__name__)
    assert grid.grid_shape == (num_cores, 1)
Ejemplo n.º 16
0
    def create_basic_single_step(self, concrete_cls) -> BlockArrayBase:
        array_cls = BlockArrayBase if concrete_cls is None else concrete_cls
        dst_ba: BlockArrayBase = array_cls(self.grid, self._system)
        if 0 in self.shape:
            return dst_ba

        src_sel_arr: np.ndarray = selection.BasicSelection.block_selection(
            self._source.shape, self._source.block_shape)
        src_sel_clipped: np.ndarray = src_sel_arr & self.sel
        assert src_sel_clipped.shape == self._source.grid.grid_shape

        broadcast_shape = self.sel.get_broadcastable_shape()
        broadcast_block_shape = self.sel.get_broadcastable_block_shape(
            dst_ba.block_shape)
        dst_grid_bc: ArrayGrid = ArrayGrid(broadcast_shape,
                                           broadcast_block_shape,
                                           self.grid.dtype.__name__)
        dst_sel_arr: np.ndarray = selection.BasicSelection.block_selection(
            broadcast_shape, broadcast_block_shape)
        dst_sel_offset: np.ndarray = dst_sel_arr + self.sel.position()
        dst_entry_iterator = list(dst_ba.grid.get_entry_iterator())
        for dst_index, dst_grid_entry_bc in enumerate(
                dst_grid_bc.get_entry_iterator()):
            dst_sel_offset_block: BasicSelection = dst_sel_offset[
                dst_grid_entry_bc]
            if dst_sel_offset_block.is_empty():
                continue
            src_dst_intersection_arr = src_sel_clipped & dst_sel_offset_block
            sys: System = self._system
            src_oids = []
            src_params = []
            dst_params = []
            for _, src_grid_entry in enumerate(
                    self._source.grid.get_entry_iterator()):
                src_dst_intersection_block: BasicSelection = src_dst_intersection_arr[
                    src_grid_entry]
                if src_dst_intersection_block.is_empty():
                    continue
                src_block: Block = self._source.blocks[src_grid_entry]
                src_oids.append(src_block.oid)
                src_sel_block: BasicSelection = src_sel_arr[src_grid_entry]
                src_dep_sel_loc = src_dst_intersection_block - src_sel_block.position(
                )
                src_params.append(
                    (src_dep_sel_loc.selector(), src_block.transposed))
                dst_block_sel_loc = src_dst_intersection_block - dst_sel_offset_block.position(
                )
                dst_params.append((dst_block_sel_loc.selector(), False))
            dst_block: Block = dst_ba.blocks.reshape(
                dst_grid_bc.grid_shape)[dst_grid_entry_bc]
            dst_block.oid = sys.create_block(
                *src_oids,
                src_params=src_params,
                dst_params=dst_params,
                dst_shape=dst_block.shape,
                dst_shape_bc=dst_sel_offset_block.get_output_shape(),
                syskwargs={
                    "grid_entry": dst_entry_iterator[dst_index],
                    "grid_shape": self.grid.grid_shape
                })
        return dst_ba
Ejemplo n.º 17
0
 def _vecdot(self, other):
     assert self.shape[-1] == other.shape[0], str(
         (self.shape[1], other.shape[0]))
     result_shape = tuple(self.shape[:-1] + other.shape[1:])
     result_block_shape = tuple(self.block_shape[:-1] +
                                other.block_shape[1:])
     result_grid = ArrayGrid(shape=result_shape,
                             block_shape=result_block_shape,
                             dtype=self.dtype.__name__)
     result = BlockArray(result_grid, self.system)
     self_num_axes = len(self.grid.grid_shape)
     other_num_axes = len(other.grid.grid_shape)
     oids = []
     for i in range(self.grid.grid_shape[-1]):
         self_grid_entry = tuple(i if axis == self_num_axes - 1 else 0
                                 for axis in range(self_num_axes))
         other_grid_entry = tuple(i if axis == 0 else 0
                                  for axis in range(other_num_axes))
         self_block: Block = self.blocks[self_grid_entry]
         other_block: Block = other.blocks[other_grid_entry]
         if self_block.transposed != other_block.transposed:
             # The vectors are aligned if their transpositions satisfy the xor relation.
             if self_block.transposed:
                 # Use other grid entry for dot,
                 # because physically,
                 # other block is located on same node as self block.
                 sch_grid_entry = other_grid_entry
                 sch_grid_shape = other.grid.grid_shape
             elif other_block.transposed:
                 # Use self grid entry for dot.
                 sch_grid_entry = self_grid_entry
                 sch_grid_shape = self.grid.grid_shape
             else:
                 raise Exception("Impossible.")
         else:
             # They're either both transposed or not.
             # Either way, one will need to be transmitted, so transmit other.
             sch_grid_entry = self_grid_entry
             sch_grid_shape = self.grid.grid_shape
         dot_oid = self.system.bop("tensordot",
                                   a1=self_block.oid,
                                   a2=other_block.oid,
                                   a1_shape=self_block.shape,
                                   a2_shape=other_block.shape,
                                   a1_T=self_block.transposed,
                                   a2_T=other_block.transposed,
                                   axes=1,
                                   syskwargs={
                                       "grid_entry": sch_grid_entry,
                                       "grid_shape": sch_grid_shape
                                   })
         oids.append(dot_oid)
     result_grid_entry = tuple(0
                               for _ in range(len(result.grid.grid_shape)))
     result_oid = self.system.sum_reduce(*oids,
                                         syskwargs={
                                             "grid_entry":
                                             result_grid_entry,
                                             "grid_shape":
                                             result.grid.grid_shape
                                         })
     result.blocks[result_grid_entry].oid = result_oid
     return result
Ejemplo n.º 18
0
def test_grid_copy():
    grid = ArrayGrid(shape=(1, 2),
                     block_shape=(1, 2),
                     dtype=np.float64.__name__)
    assert grid.copy() is not grid
Ejemplo n.º 19
0
    def basic_assign_single_step(self, dst_sel: BasicSelection, value):
        assert isinstance(value, (ArrayView, BlockArrayBase))

        dst_ba: BlockArrayBase = self._source
        dst_sel_arr: np.ndarray = selection.BasicSelection.block_selection(dst_ba.shape,
                                                                           dst_ba.block_shape)

        dst_sel_clipped: np.ndarray = dst_sel_arr & dst_sel
        assert dst_sel_clipped.shape == self._source.grid.grid_shape

        # We create value's block array, in case we need to broadcast.
        # This may not be necessary, but alternative solutions are extremely tedious.
        # The result is a block array with replicated blocks,
        # which match the output shape of dst_sel.
        if isinstance(value, ArrayView):
            src_ba_bc: BlockArrayBase = value.create().broadcast_to(dst_sel.get_output_shape())
        elif isinstance(value, BlockArrayBase):
            src_ba_bc: BlockArrayBase = value.broadcast_to(dst_sel.get_output_shape())
        else:
            raise Exception("Unexpected value type %s." % type(value))
        # Different lengths occur when an index is used to perform
        # a selection on an axis. Numpy semantics drops such axes. To allow operations
        # between source and destination selections, dropped axes are restored with dimension 1
        # so that selections are of equal length.
        # We restore the dropped dimensions of the destination selection, because
        # the source selection must be broadcastable to the destination selection
        # for the assignment to be valid.
        src_inflated_shape = dst_sel.get_broadcastable_shape()
        # The block shapes need not be equal, but the broadcast source block shape must
        # match the block shape we obtain below, so that there's a 1-to-1 correspondence
        # between the grid entries.
        src_inflated_block_shape = dst_sel.get_broadcastable_block_shape(src_ba_bc.block_shape)
        src_inflated_grid: ArrayGrid = ArrayGrid(src_inflated_shape,
                                                 src_inflated_block_shape,
                                                 self.grid.dtype.__name__)
        src_sel_arr: np.ndarray = selection.BasicSelection.block_selection(src_inflated_shape,
                                                                           src_inflated_block_shape)
        src_sel_offset: np.ndarray = src_sel_arr + dst_sel.position()
        # The enumeration of grid entries is identical if the broadcast source grid and
        # inflated grid have the same number of blocks.
        src_grid_entry_iterator = list(src_ba_bc.grid.get_entry_iterator())
        for dst_grid_entry in dst_ba.grid.get_entry_iterator():
            dst_sel_block: BasicSelection = dst_sel_arr[dst_grid_entry]
            dst_sel_block_clipped: BasicSelection = dst_sel_clipped[dst_grid_entry]
            if dst_sel_block_clipped.is_empty():
                continue
            src_intersection_arr = src_sel_offset & dst_sel_block_clipped
            src_oids = []
            src_params = []
            dst_params = []
            dst_block: Block = dst_ba.blocks[dst_grid_entry]
            for src_index, src_grid_entry_bc in enumerate(src_inflated_grid.get_entry_iterator()):
                src_intersection_block: BasicSelection = src_intersection_arr[src_grid_entry_bc]
                if src_intersection_block.is_empty():
                    continue

                src_grid_entry = src_grid_entry_iterator[src_index]
                src_block: Block = src_ba_bc.blocks[src_grid_entry]
                src_oids.append(src_block.oid)

                src_sel_block_offset: BasicSelection = src_sel_offset[src_grid_entry_bc]
                src_dep_sel_loc = src_intersection_block - src_sel_block_offset.position()
                src_params.append((src_dep_sel_loc.selector(),
                                   src_sel_block_offset.get_output_shape(),
                                   src_block.transposed))
                # We're looking at intersection of dst block and src block, so the
                # location to which we assign must be offset by dst_sel_block.
                dst_block_sel_loc: BasicSelection = (src_intersection_block
                                                     - dst_sel_block.position())
                dst_params.append((dst_block_sel_loc.selector(), dst_block.transposed))
            if len(src_oids) == 0:
                continue
            dst_block.oid = self._system.update_block(dst_block.oid,
                                                      *src_oids,
                                                      src_params=src_params,
                                                      dst_params=dst_params,
                                                      syskwargs={
                                                          "grid_entry": dst_block.grid_entry,
                                                          "grid_shape": dst_block.grid_shape
                                                      })