Esempio n. 1
0
 def visit_Subscript(self, node: ast.Subscript) -> Any:
     # Convert subscript to symbol name
     node_name = astutils.rname(node)
     if node_name in self.iconns:
         self.latest[node_name] += 1
         new_name = f'{node_name}_{self.latest[node_name]}'
         subset = subsets.Range(
             astutils.subscript_to_slice(node, self.sdfg.arrays)[1])
         # Check if range can be collapsed
         if _range_is_promotable(subset, self.defined):
             self.in_mapping[new_name] = (node_name, subset)
             return ast.copy_location(ast.Name(id=new_name, ctx=ast.Load()),
                                      node)
         else:
             self.do_not_remove.add(node_name)
     elif node_name in self.oconns:
         self.latest[node_name] += 1
         new_name = f'{node_name}_{self.latest[node_name]}'
         subset = subsets.Range(
             astutils.subscript_to_slice(node, self.sdfg.arrays)[1])
         # Check if range can be collapsed
         if _range_is_promotable(subset, self.defined):
             self.out_mapping[new_name] = (node_name, subset)
             return ast.copy_location(
                 ast.Name(id=new_name, ctx=ast.Store()), node)
         else:
             self.do_not_remove.add(node_name)
     return self.generic_visit(node)
Esempio n. 2
0
    def delinearize_linearize(
            self, desc: data.Array, copy_shape: Tuple[symbolic.SymbolicType],
            rng: subsets.Range) -> Tuple[symbolic.SymbolicType]:
        """
        Converts one N-dimensional iteration space to another M-dimensional space via linearization
        followed by delinearization.
        """
        indices = [
            symbolic.pystr_to_symbolic(f'__i{i}')
            for i in range(len(copy_shape))
        ]

        # Special case for when both dimensionalities are equal
        if tuple(desc.shape) == tuple(copy_shape):
            return subsets.Range([(ind, ind, 1) for ind in indices])

        if rng is not None:  # Deal with offsets and strides in range
            indices = rng.coord_at(indices)

        linear_index = sum(indices[i] * data._prod(copy_shape[i + 1:])
                           for i in range(len(indices)))

        cur_index = [0] * len(desc.shape)
        divide_by = 1
        for i in reversed(range(len(desc.shape))):
            cur_index[i] = (linear_index / divide_by) % desc.shape[i]
            divide_by = divide_by * desc.shape[i]

        return subsets.Range([(ind, ind, 1) for ind in cur_index])
Esempio n. 3
0
    def propagate(self, array, expressions, node_range):
        result = [(None, None, None)] * len(self.patterns_per_dim)

        overapprox_range = subsets.Range([
            (rb.approx if isinstance(rb, symbolic.SymExpr) else rb,
             re.approx if isinstance(re, symbolic.SymExpr) else re,
             rs.approx if isinstance(rs, symbolic.SymExpr) else rs)
            for rb, re, rs in node_range
        ])

        for i, smpattern in enumerate(self.patterns_per_dim):

            dexprs = []
            for expr in expressions:
                if isinstance(expr[i], symbolic.SymExpr):
                    dexprs.append(expr[i].approx)
                elif isinstance(expr[i], tuple):
                    dexprs.append(
                        (expr[i][0].approx if isinstance(
                            expr[i][0], symbolic.SymExpr) else expr[i][0],
                         expr[i][1].approx if isinstance(
                             expr[i][1], symbolic.SymExpr) else expr[i][1],
                         expr[i][2].approx if isinstance(
                             expr[i][2], symbolic.SymExpr) else expr[i][2],
                         expr.tile_sizes[i]))
                else:
                    dexprs.append(expr[i])

            result[i] = smpattern.propagate(array, dexprs, overapprox_range)

        # TODO(later): Not necessarily Range (general integer sets)
        return subsets.Range(result)
Esempio n. 4
0
    def coverage_dicts(sdfg, graph, map_entry, outer_range=True):
        '''
        returns a tuple of two dicts:
        the first dict has as a key all data entering the map
        and its associated access range
        the second dict has as a key all data exiting the map
        and its associated access range
        if outer_range = True, substitutes outer ranges
        into min/max of inner access range
        '''
        map_exit = graph.exit_node(map_entry)
        map = map_entry.map

        entry_coverage = {}
        exit_coverage = {}
        # create dicts with which we can replace all iteration
        # variable_mapping by their range
        map_min = {dace.symbol(param): e for param, e in zip(map.params, map.range.min_element())}
        map_max = {dace.symbol(param): e for param, e in zip(map.params, map.range.max_element())}

        # look at inner memlets at map entry
        for e in graph.out_edges(map_entry):
            if not e.data.subset:
                continue
            if outer_range:
                # get subset
                min_element = [m.subs(map_min) for m in e.data.subset.min_element()]
                max_element = [m.subs(map_max) for m in e.data.subset.max_element()]
                # create range
                rng = subsets.Range((min_e, max_e, 1) for min_e, max_e in zip(min_element, max_element))
            else:
                rng = dcpy(e.data.subset)

            if e.data.data not in entry_coverage:
                entry_coverage[e.data.data] = rng
            else:
                old_coverage = entry_coverage[e.data.data]
                entry_coverage[e.data.data] = subsets.union(old_coverage, rng)

        # look at inner memlets at map exit
        for e in graph.in_edges(map_exit):
            if outer_range:
                # get subset
                min_element = [m.subs(map_min) for m in e.data.subset.min_element()]
                max_element = [m.subs(map_max) for m in e.data.subset.max_element()]
                # craete range
                rng = subsets.Range((min_e, max_e, 1) for min_e, max_e in zip(min_element, max_element))
            else:
                rng = dcpy(e.data.subset)

            if e.data.data not in exit_coverage:
                exit_coverage[e.data.data] = rng
            else:
                old_coverage = exit_coverage[e.data]
                exit_coverage[e.data.data] = subsets.union(old_coverage, rng)

        # return both coverages as a tuple
        return (entry_coverage, exit_coverage)
Esempio n. 5
0
def test_intersects_constant():
    rng1 = subsets.Range([(0, 4, 1)])
    rng2 = subsets.Range([(3, 4, 1)])
    rng3 = subsets.Range([(1, 5, 1)])
    rng4 = subsets.Range([(5, 7, 1)])
    ind1 = subsets.Indices([0])
    ind2 = subsets.Indices([1])
    ind3 = subsets.Indices([5])

    assert subsets.intersects(rng1, rng2) is True
    assert subsets.intersects(rng1, rng3) is True
    assert subsets.intersects(rng1, rng4) is False
    assert subsets.intersects(ind1, rng1) is True
    assert subsets.intersects(rng1, ind2) is True
    assert subsets.intersects(rng1, ind3) is False
Esempio n. 6
0
 def from_memlet(memlet: 'Memlet') -> 'Memlet':
     sbs = subsets.Range(
         memlet.subset.ndrange()) if memlet.subset is not None else None
     osbs = subsets.Range(memlet.other_subset.ndrange()
                          ) if memlet.other_subset is not None else None
     result = Memlet(data=memlet.data,
                     subset=sbs,
                     other_subset=osbs,
                     volume=memlet.volume,
                     dynamic=memlet.dynamic,
                     wcr=memlet.wcr,
                     debuginfo=copy(memlet.debuginfo),
                     wcr_nonatomic=memlet.wcr_nonatomic,
                     allow_oob=memlet.allow_oob)
     result._is_data_src = memlet._is_data_src
     return result
Esempio n. 7
0
    def _create_strided_range(self, sdfg: SDFG, state: SDFGState,
                              map_entry: nodes.MapEntry):
        map_exit = state.exit_node(map_entry)
        dim_idx = self.dim_idx
        new_dim_prefix = self.new_dim_prefix
        tile_size = self.tile_size
        divides_evenly = self.divides_evenly
        tile_stride = self.tile_stride
        if tile_stride == 0:
            tile_stride = tile_size
        if tile_stride != tile_size:
            raise NotImplementedError

        # Retrieve parameter and range of dimension to be strip-mined.
        target_dim = map_entry.map.params[dim_idx]
        td_from, td_to, td_step = map_entry.map.range[dim_idx]
        new_dim = self._find_new_dim(sdfg, state, map_entry, new_dim_prefix,
                                     target_dim)
        new_dim_range = (td_from, td_to, tile_size)
        new_map = nodes.Map(map_entry.map.label, [new_dim],
                            subsets.Range([new_dim_range]))

        dimsym = dace.symbolic.pystr_to_symbolic(new_dim)
        td_from_new = dimsym
        if divides_evenly:
            td_to_new = dimsym + tile_size - 1
        else:
            if isinstance(td_to, dace.symbolic.SymExpr):
                td_to = td_to.expr
            td_to_new = dace.symbolic.SymExpr(
                sympy.Min(dimsym + tile_size - 1, td_to),
                dimsym + tile_size - 1)
        td_step_new = td_step

        return new_dim, new_map, (td_from_new, td_to_new, td_step_new)
Esempio n. 8
0
def _make_full_range(memlet: astnodes._Memlet):
    fullRange = sbs.Range([(0, s - 1, 1) for s in memlet.data.shape])
    fullMemlet = astnodes._Memlet(memlet.data,
                                  memlet.dataname, memlet.attribute,
                                  fullRange.num_elements(), None, None,
                                  fullRange, memlet.veclen, None, None, {})
    return fullMemlet
Esempio n. 9
0
 def _offset_refine(
     torefine: Dict[str, Tuple[Memlet, Set[int]]],
     outer_edges: Callable[[nodes.NestedSDFG, str],
                           Iterable[MultiConnectorEdge[Memlet]]]):
     # Offset memlets inside negatively by "refine", modify outer
     # memlets to be "refine"
     for aname, (refine, indices) in torefine.items():
         outer_edge = next(iter(outer_edges(nsdfg_node, aname)))
         new_memlet = helpers.unsqueeze_memlet(refine, outer_edge.data)
         outer_edge.data.subset = subsets.Range([
             ns if i in indices else os for i, (os, ns) in enumerate(
                 zip(outer_edge.data.subset, new_memlet.subset))
         ])
         if aname in refined:
             continue
         # Refine internal memlets
         for nstate in nsdfg.nodes():
             for e in nstate.edges():
                 if e.data.data == aname:
                     e.data.subset.offset(refine.subset, True, indices)
         # Refine accesses in interstate edges
         refiner = ASTRefiner(aname, refine.subset, nsdfg, indices)
         for isedge in nsdfg.edges():
             for k, v in isedge.data.assignments.items():
                 vast = ast.parse(v)
                 refiner.visit(vast)
                 isedge.data.assignments[k] = astutils.unparse(vast)
             if isedge.data.condition.language is dtypes.Language.Python:
                 for i, stmt in enumerate(isedge.data.condition.code):
                     isedge.data.condition.code[i] = refiner.visit(stmt)
             else:
                 raise NotImplementedError
         refined.add(aname)
Esempio n. 10
0
def calc_set_image_range(map_idx, map_set, array_range):
    image = []
    for a_range in array_range:
        new_range = list(a_range)
        for m_idx, m_range in zip(map_idx, map_set):
            symbol = symbolic.pystr_to_symbolic(m_idx)
            for i in range(3):
                if isinstance(m_range[i], SymExpr):
                    exact = m_range[i].expr
                    approx = m_range[i].approx
                else:
                    exact = m_range[i]
                    approx = overapproximate(m_range[i])
                if isinstance(new_range[i], SymExpr):
                    new_range[i] = SymExpr(
                        new_range[i].expr.subs([(symbol, exact)]),
                        new_range[i].approx.subs([(symbol, approx)]))
                elif issymbolic(new_range[i]):
                    new_range[i] = SymExpr(
                        new_range[i].subs([(symbol, exact)]),
                        new_range[i].subs([(symbol, approx)]))
                else:
                    new_range[i] = SymExpr(new_range[i], new_range[i])
        image.append(new_range)
    return subsets.Range(image)
Esempio n. 11
0
def calc_set_union(set_a, set_b):
    if isinstance(set_a, subsets.Indices) or isinstance(set_b, subsets.Indices):
        raise NotImplementedError('Set union with indices is not implemented.')
    if not (isinstance(set_a, subsets.Range) and isinstance(set_b, subsets.Range)):
        raise TypeError('Can only compute the union of ranges.')
    if len(set_a) != len(set_b):
        raise ValueError('Range dimensions do not match')
    union = []
    for range_a, range_b in zip(set_a, set_b):
        r_union = []
        for i in range(3):
            if isinstance(range_a[i], SymExpr):
                a_exact = range_a[i].expr
                a_approx = range_a[i].approx
            else:
                a_exact = range_a[i]
                a_approx = range_a[i]
            if isinstance(range_b[i], SymExpr):
                b_exact = range_b[i].expr
                b_approx = range_b[i].approx
            else:
                b_exact = range_b[i]
                b_approx = range_b[i]
            if i in {0, 2}:
                r_union.append(SymExpr(sympy.Min(a_exact, b_exact), sympy.Min(a_approx, b_approx)))
            else:
                r_union.append(SymExpr(sympy.Max(a_exact, b_exact), sympy.Max(a_approx, b_approx)))
        union.append(r_union)
        # union.append([
        #     sympy.Min(range_a[0], range_b[0]),
        #     sympy.Max(range_a[1], range_b[1]),
        #     sympy.Min(range_a[2], range_b[2]),
        # ])
    return subsets.Range(union)
Esempio n. 12
0
def parse_memlet_subset(array: data.Data, node: Union[ast.Name, ast.Subscript],
                        das: Dict[str, Any],
                        parsed_slice: Any = None) -> Tuple[subsets.Range, List[int]]:
    """ 
    Parses an AST subset and returns access range, as well as new dimensions to
    add.
    :param array: Accessed data descriptor (used for filling in missing data, 
                  e.g., negative indices or empty shapes).
    :param node: AST node representing whole array or subset thereof.
    :param das: Dictionary of defined arrays and symbols mapped to their values.
    :return: A 2-tuple of (subset, list of new axis indices).
    """
    # Get memlet range
    ndslice = [(0, s - 1, 1) for s in array.shape]
    extra_dims = []
    arrdims: Dict[int, str] = {}
    if isinstance(node, ast.Subscript):
        # Parse and evaluate ND slice(s) (possibly nested)
        if parsed_slice:
            cnode = copy.deepcopy(node)
            cnode.slice = parsed_slice
        else:
            cnode = node
        ast_ndslices = astutils.subscript_to_ast_slice_recursive(cnode)
        offsets = list(range(len(array.shape)))

        # Loop over nd-slices (A[i][j][k]...)
        subset_array = []
        for idx, ast_ndslice in enumerate(ast_ndslices):
            # Cut out dimensions that were indexed in the previous slice
            narray = copy.deepcopy(array)
            narray.shape = [
                s for i, s in enumerate(array.shape) if i in offsets
            ]

            # Loop over the N dimensions
            ndslice, offsets, new_extra_dims, arrdims = _fill_missing_slices(
                das, ast_ndslice, narray, offsets)
            if new_extra_dims and idx != (len(ast_ndslices) - 1):
                raise NotImplementedError('New axes only implemented for last '
                                          'slice')
            if arrdims and len(ast_ndslices) != 1:
                raise NotImplementedError('Array dimensions not implemented '
                                          'for consecutive subscripts')
            extra_dims = new_extra_dims
            subset_array.append(_ndslice_to_subset(ndslice))

        subset = subset_array[0]

        # Compose nested indices, e.g., of the form "A[i,:,j,:][k,l]"
        for i in range(1, len(subset_array)):
            subset = subset.compose(subset_array[i])

    else:  # Use entire range
        subset = _ndslice_to_subset(ndslice)

    if isinstance(subset, subsets.Indices):
        subset = subsets.Range([(i, i, 1) for i in subset])
    return subset, extra_dims, arrdims
Esempio n. 13
0
    def _modify_memlet(sdfg, subset, data_name):
        desc = sdfg.arrays[data_name]
        if len(subset) == len(desc.shape):
            # Already in the right shape, modify new dimension
            subset = list(subset)[1:]

        new_subset = subsets.Range([('__dace_db_param', '__dace_db_param',
                                     1)] + list(subset))
        return new_subset
Esempio n. 14
0
def calc_set_image_index(map_idx, map_set, array_idx):
    image = []
    for a_idx in array_idx.indices:
        new_range = [a_idx, a_idx, 1]
        for m_idx, m_range in zip(map_idx, map_set):
            symbol = symbolic.pystr_to_symbolic(m_idx)
            new_range[0] = new_range[0].subs(symbol, m_range[0])
            new_range[1] = new_range[1].subs(symbol, m_range[1])
        image.append(new_range)
    return subsets.Range(image)
Esempio n. 15
0
    def _Subscript(self, t: ast.Subscript):
        from dace.frontend.python.astutils import subscript_to_slice
        target, rng = subscript_to_slice(t, self.sdfg.arrays)
        rng = subsets.Range(rng)
        if rng.num_elements() != 1:
            raise SyntaxError(
                'Range subscripts disallowed in interstate edges')

        memlet = mmlt.Memlet(data=target, subset=rng)
        self.write(cpp_array_expr(self.sdfg, memlet))
Esempio n. 16
0
    def visit_Subscript(self, node: ast.Subscript) -> ast.Subscript:
        if astutils.rname(node.value) == self.to_refine:
            rng = subsets.Range(
                astutils.subscript_to_slice(node,
                                            self.sdfg.arrays,
                                            without_array=True))
            rng.offset(self.subset, True, self.indices)
            return ast.copy_location(
                astutils.slice_to_subscript(self.to_refine, rng), node)

        return self.generic_visit(node)
Esempio n. 17
0
def calc_set_image_range(map_idx, map_set, array_range):
    image = []
    for a_range in array_range:
        new_range = a_range
        for m_idx, m_range in zip(map_idx, map_set):
            symbol = symbolic.pystr_to_symbolic(m_idx)
            new_range = [
                new_range[i].subs(symbol, m_range[i]) for i in range(0, 3)
            ]
        image.append(new_range)
    return subsets.Range(image)
Esempio n. 18
0
def _ndslice_to_subset(ndslice):
    is_tuple = [isinstance(x, tuple) for x in ndslice]
    if not any(is_tuple):
        return subsets.Indices(ndslice)
    else:
        if not all(is_tuple):
            # If a mix of ranges and indices is found, convert to range
            for i in range(len(ndslice)):
                if not is_tuple[i]:
                    ndslice[i] = (ndslice[i], ndslice[i], 1)
        return subsets.Range(ndslice)
Esempio n. 19
0
def dirichlet_tasklet(state, B, x0, y0, width, height, initval=0):
    # Set up map that only has a write output, without any input. This generates an empty memlet from the map
    # entry to the tasklet automatically
    _, me, mx = state.add_mapped_tasklet(
        'boundary',
        dict(i='%s:%s' % (y0, y0 + height), j='%s:%s' % (x0, x0 + width)), {},
        '''b = %f''' % initval,
        dict(b=dace.Memlet(data=B.data, subset='i,j')),
        external_edges=False)
    # Add the edge directly (i.e, without string parsing) using a Range object.
    # Notice that ranges are internally INCLUSIVE.
    out_subset = subsets.Range([(y0, y0 + height - 1, 1),
                                (x0, x0 + width - 1, 1)])
    state.add_nedge(mx, B, dace.Memlet(data=B.data, subset=out_subset))
Esempio n. 20
0
def calc_set_image_range(map_idx, map_set, array_range):
    image = []
    for a_range in array_range:
        new_range = a_range
        for m_idx, m_range in zip(map_idx, map_set):
            symbol = symbolic.pystr_to_symbolic(m_idx)
            new_range = [
                new_range[i].subs(symbol,
                                  dace.symbolic.overapproximate(m_range[i]))
                if dace.symbolic.issymbolic(new_range[i]) else new_range[i]
                for i in range(0, 3)
            ]
        image.append(new_range)
    return subsets.Range(image)
Esempio n. 21
0
        def _check_cand(candidates, outer_edges):
            for cname, (cand, nstate, indices) in candidates.items():
                if all(me == 0
                       for i, me in enumerate(cand.subset.min_element())
                       if i in indices):
                    ignore.add(cname)
                    continue

                # Ensure outer memlets begin with 0
                outer_edge = next(iter(outer_edges(nsdfg, cname)))
                if any(me != 0 for i, me in enumerate(
                        outer_edge.data.subset.min_element()) if i in indices):
                    ignore.add(cname)
                    continue

                # Check w.r.t. loops
                if len(nstate.ranges) > 0:
                    # Re-annotate loop ranges, in case someone changed them
                    # TODO: Move out of here!
                    nstate.ranges = {}
                    from dace.sdfg.propagation import _annotate_loop_ranges
                    _annotate_loop_ranges(nsdfg.sdfg, [])

                    memlet = propagation.propagate_subset(
                        [cand], nsdfg.sdfg.arrays[cname],
                        sorted(nstate.ranges.keys()),
                        subsets.Range([
                            v.ndrange()[0]
                            for _, v in sorted(nstate.ranges.items())
                        ]))
                    if all(me == 0
                           for i, me in enumerate(memlet.subset.min_element())
                           if i in indices):
                        ignore.add(cname)
                        continue

                    # Modify memlet to propagated one
                    candidates[cname] = (memlet, nstate, indices)
                else:
                    memlet = cand

                # If there are any symbols here that are not defined
                # in "defined_symbols"
                missing_symbols = (memlet.free_symbols -
                                   set(nsdfg.symbol_mapping.keys()))
                if missing_symbols:
                    ignore.add(cname)
                    continue
Esempio n. 22
0
def parse_memlet_subset(array: data.Data, node: Union[ast.Name, ast.Subscript],
                        das: Dict[str, Any]):
    array_dependencies = {}

    # Get memlet range
    ndslice = [(0, s - 1, 1) for s in array.shape]
    if isinstance(node, ast.Subscript):
        # Parse and evaluate ND slice(s) (possibly nested)
        ast_ndslices = astutils.subscript_to_ast_slice_recursive(node)
        offsets = list(range(len(array.shape)))

        # Loop over nd-slices (A[i][j][k]...)
        subset_array = []
        for ast_ndslice in ast_ndslices:
            # Cut out dimensions that were indexed in the previous slice
            narray = copy.deepcopy(array)
            narray.shape = [
                s for i, s in enumerate(array.shape) if i in offsets
            ]

            # Loop over the N dimensions
            ndslice, offsets = _fill_missing_slices(das, ast_ndslice, narray,
                                                    offsets)
            subset_array.append(_ndslice_to_subset(ndslice))

        subset = subset_array[0]

        # Compose nested indices, e.g., of the form "A[i,:,j,:][k,l]"
        for i in range(1, len(subset_array)):
            subset = subset.compose(subset_array[i])

        # Compute additional array dependencies (as a result of
        # indirection)
        # for dim in subset:
        #     if not isinstance(dim, tuple): dim = [dim]
        #     for r in dim:
        #         for expr in symbolic.swalk(r):
        #             if symbolic.is_sympy_userfunction(expr):
        #                 arr = expr.func.__name__
        #                 array_dependencies[arr] = self.curnode.globals[arr]

    else:  # Use entire range
        subset = _ndslice_to_subset(ndslice)

    if isinstance(subset, subsets.Indices):
        subset = subsets.Range([(i, i, 1) for i in subset])
    return subset
Esempio n. 23
0
def calc_set_union(set_a, set_b):
    if isinstance(set_a, subsets.Indices) or isinstance(
            set_b, subsets.Indices):
        raise NotImplementedError('Set union with indices is not implemented.')
    if not (isinstance(set_a, subsets.Range)
            and isinstance(set_b, subsets.Range)):
        raise TypeError('Can only compute the union of ranges.')
    if len(set_a) != len(set_b):
        raise ValueError('Range dimensions do not match')
    union = []
    for range_a, range_b in zip(set_a, set_b):
        union.append([
            sympy.Min(range_a[0], range_b[0]),
            sympy.Max(range_a[1], range_b[1]),
            sympy.Min(range_a[2], range_b[2]),
        ])
    return subsets.Range(union)
Esempio n. 24
0
def pop_dims(subset, dims):
    popped = []
    if isinstance(subset, subsets.Indices):
        indices = copy.deepcopy(subsets.Indices)
        for i in dims:
            popped.append(indices.pop(i))
        return subsets.Indices(indices)
    else:
        ranges = copy.deepcopy(subset.ranges)
        tsizes = copy.deepcopy(subset.tile_sizes)
        for i in dims:
            r = ranges.pop(i)
            t = tsizes.pop(i)
            popped.append((r, t))
        new_subset = subsets.Range(ranges)
        new_subset.tile_sizes = tsizes
        return new_subset, popped
Esempio n. 25
0
    def propagate(self, array, expressions, node_range):
        rng = [(None, None, 1)] * len(array.shape)
        node_range_gen = (range(rb, re, rs) for rb, re, rs in node_range)
        for ndind in itertools.product(*tuple(node_range_gen)):
            repldict = {p: ndind[i] for i, p in enumerate(self.params)}
            for expr in expressions:
                for dim, dexpr in enumerate(expr):
                    evaldexpr = _subexpr(dexpr, repldict)
                    rb, re, rs = rng[dim]
                    if rb is None:
                        rng[dim] = (evaldexpr, evaldexpr, 1)
                    else:
                        if evaldexpr < rb:
                            rng[dim] = (evaldexpr, re, rs)
                        if evaldexpr > re:  # The +1 is because ranges are exclusive
                            rng[dim] = (rb, evaldexpr, rs)

        return subsets.Range(rng)
Esempio n. 26
0
def test_intersects_symbolic():
    N, M = dace.symbol('N', positive=True), dace.symbol('M', positive=True)
    rng1 = subsets.Range([(0, N - 1, 1), (0, M - 1, 1)])
    rng2 = subsets.Range([(0, 0, 1), (0, 0, 1)])
    rng3_1 = subsets.Range([(N, N, 1), (0, 1, 1)])
    rng3_2 = subsets.Range([(0, 1, 1), (M, M, 1)])
    rng4 = subsets.Range([(N, N, 1), (M, M, 1)])
    rng5 = subsets.Range([(0, 0, 1), (M, M, 1)])
    rng6 = subsets.Range([(0, N, 1), (0, M, 1)])
    rng7 = subsets.Range([(0, N - 1, 1), (N - 1, N, 1)])
    ind1 = subsets.Indices([0, 1])

    assert subsets.intersects(rng1, rng2) is True
    assert subsets.intersects(rng1, rng3_1) is False
    assert subsets.intersects(rng1, rng3_2) is False
    assert subsets.intersects(rng1, rng4) is False
    assert subsets.intersects(rng1, rng5) is False
    assert subsets.intersects(rng6, rng1) is True
    assert subsets.intersects(rng1, rng7) is None
    assert subsets.intersects(rng7, rng1) is None
    assert subsets.intersects(rng1, ind1) is None
    assert subsets.intersects(ind1, rng1) is None
Esempio n. 27
0
def compose_and_push_back(first, second, dims=None, popped=None):
    if isinstance(first, subsets.Indices):
        subset = first.new_offset(second, negative=False)
    else:
        subset = first.compose(second)
    if dims and popped and len(dims) == len(popped):
        if isinstance(first, subsets.Indices):
            indices = subset.Indices
            for d, p in zip(reversed(dims), reversed(popped)):
                indices.insert(d, p)
            subset = subsets.Indices(indices)
        else:
            ranges = subset.ranges
            tsizes = subset.tile_sizes
            for d, (r, t) in zip(reversed(dims), reversed(popped)):
                ranges.insert(d, r)
                tsizes.insert(d, t)
            subset = subsets.Range(ranges)
            subset.tile_sizes = tsizes
    return subset
Esempio n. 28
0
def calc_set_image_range(map_idx, map_set, array_range):
    image = []
    for a_range in array_range:
        new_range = list(a_range)
        for m_idx, m_range in zip(map_idx, map_set):
            symbol = symbolic.pystr_to_symbolic(m_idx)
            for i in range(3):
                if isinstance(m_range[i], SymExpr):
                    exact = m_range[i].expr
                    approx = m_range[i].approx
                else:
                    exact = m_range[i]
                    approx = overapproximate(m_range[i])
                if isinstance(new_range[i], SymExpr):
                    new_range[i] = SymExpr(
                        new_range[i].expr.subs([(symbol, exact)]),
                        new_range[i].approx.subs([(symbol, approx)]))
                elif issymbolic(new_range[i]):
                    new_range[i] = SymExpr(
                        new_range[i].subs([(symbol, exact)]),
                        new_range[i].subs([(symbol, approx)]))
                else:
                    new_range[i] = SymExpr(new_range[i], new_range[i])
            if isinstance(new_range[0], SymExpr):
                start = new_range[0].approx
            else:
                start = new_range[0]
            if isinstance(new_range[1], SymExpr):
                stop = new_range[1].approx
            else:
                stop = new_range[1]
            if isinstance(new_range[2], SymExpr):
                step = new_range[2].approx
            else:
                step = new_range[2]
            descending = (start > stop) == True
            posstep = (step > 0) == True
            if descending and posstep:
                new_range[0], new_range[1] = new_range[1], new_range[0]
        image.append(new_range)
    return subsets.Range(image)
Esempio n. 29
0
    def _create_from_tile_numbers(self, sdfg: SDFG, state: SDFGState,
                                  map_entry: nodes.MapEntry):
        map_exit = state.exit_node(map_entry)

        # Retrieve transformation properties.
        dim_idx = self.dim_idx
        new_dim_prefix = self.new_dim_prefix
        divides_evenly = self.divides_evenly
        number_of_tiles = self.tile_size
        tile_stride = self.tile_stride

        number_of_tiles = dace.symbolic.pystr_to_symbolic(number_of_tiles)

        # Retrieve parameter and range of dimension to be strip-mined.
        target_dim = map_entry.map.params[dim_idx]
        td_from, td_to, td_step = map_entry.map.range[dim_idx]
        tile_size = map_entry.map.range.size_exact()[dim_idx] / number_of_tiles

        if tile_stride == 0:
            tile_stride = tile_size
        if tile_stride != tile_size:
            raise NotImplementedError

        new_dim = self._find_new_dim(sdfg, state, map_entry, new_dim_prefix,
                                     target_dim)
        new_dim_range = (td_from, number_of_tiles - 1, 1)
        new_map = nodes.Map(map_entry.map.label, [new_dim],
                            subsets.Range([new_dim_range]))

        dimsym = dace.symbolic.pystr_to_symbolic(new_dim)
        td_from_new = dimsym * tile_size
        if divides_evenly:
            td_to_new = (dimsym + 1) * tile_size - 1
        else:
            if isinstance(td_to, dace.symbolic.SymExpr):
                td_to = td_to.expr
            td_to_new = dace.symbolic.SymExpr(
                sympy.Min((dimsym + 1) * tile_size - 1, td_to),
                (dimsym + 1) * tile_size - 1)
        td_step_new = td_step
        return new_dim, new_map, (td_from_new, td_to_new, td_step_new)
Esempio n. 30
0
def calc_set_image_range(map_idx, map_set, array_range, strided):
    image = []
    n = len(array_range) - len(strided)
    if n > 0:
        strided.append([strided[-1]] * n)
    for a_range, stride in zip(array_range, strided):
        new_range = list(a_range)
        for m_idx, m_range in zip(map_idx, map_set):
            symbol = symbolic.pystr_to_symbolic(m_idx)
            new_range[0] = new_range[0].subs(
                symbol, dace.symbolic.overapproximate(m_range[0]))
            new_range[1] = new_range[1].subs(
                symbol, dace.symbolic.overapproximate(m_range[1]))
            if stride:
                new_range[2] = symbolic.pystr_to_symbolic('%s / %s' % (str(
                    new_range[2]), symbolic.symstr(m_range[1])))
            else:
                new_range[2] = new_range[2].subs(
                    symbol, dace.symbolic.overapproximate(m_range[2]))
        image.append(new_range)
    return subsets.Range(image)