コード例 #1
0
    def apply(self, sdfg):
        def gnode(nname):
            return graph.nodes()[self.subgraph[nname]]

        graph = sdfg.nodes()[self.state_id]
        in_array = gnode(RedundantArray._in_array)
        out_array = gnode(RedundantArray._out_array)

        for e in graph.in_edges(in_array):
            # Modify all incoming edges to point to out_array
            path = graph.memlet_path(e)
            for pe in path:
                if pe.data.data == in_array.data:
                    pe.data.data = out_array.data

            # Redirect edge to out_array
            graph.remove_edge(e)
            graph.add_edge(e.src, e.src_conn, out_array, e.dst_conn, e.data)

        # Finally, remove in_array node
        graph.remove_node(in_array)
        # TODO: Should the array be removed from the SDFG?
        # del sdfg.arrays[in_array]
        if Config.get_bool("debugprint"):
            RedundantArray._arrays_removed += 1
コード例 #2
0
    def apply(self, sdfg):
        def gnode(nname):
            return graph.nodes()[self.subgraph[nname]]

        graph = sdfg.nodes()[self.state_id]
        in_array = gnode(RedundantSecondArray._in_array)
        out_array = gnode(RedundantSecondArray._out_array)

        # We assume the following pattern: A -- e1 --> B -- e2 --> others

        # 1. Get edge e1 and extract subsets for arrays A and B
        e1 = graph.edges_between(in_array, out_array)[0]
        a_subset, b1_subset = _validate_subsets(e1, sdfg.arrays)
        # 2. Iterate over the e2 edges and traverse the memlet tree
        for e2 in graph.out_edges(out_array):
            path = graph.memlet_tree(e2)
            for e3 in path:
                # 2-a. Extract subsets for array B and others
                b3_subset, other_subset = _validate_subsets(
                    e3, sdfg.arrays, src_name=out_array.data)
                # 2-b. Modify memlet to match array A. Example:
                # A -- (0, a:b)/(c:c+b) --> B -- (c+d)/None --> others
                # A -- (0, a+d)/None --> others
                e3.data.data = in_array.data
                # (c+d) - (c:c+b) = (d)
                b3_subset.offset(b1_subset, negative=True)
                # (0, a:b)(d) = (0, a+d) (or offset for indices)
                if isinstance(a_subset, subsets.Indices):
                    tmp = copy.deepcopy(a_subset)
                    tmp.offset(b3_subset, negative=False)
                    e3.data.subset = tmp
                else:
                    e3.data.subset = a_subset.compose(b3_subset)
                e3.data.other_subset = other_subset
            # 2-c. Remove edge and add new one
            graph.remove_edge(e2)
            graph.add_edge(in_array, e2.src_conn, e2.dst, e2.dst_conn, e2.data)

        # Finally, remove out_array node
        graph.remove_node(out_array)
        # TODO: Should the array be removed from the SDFG?
        # del sdfg.arrays[out_array]
        if Config.get_bool("debugprint"):
            RedundantSecondArray._arrays_removed += 1
コード例 #3
0
ファイル: redundant_array.py プロジェクト: thobauma/dace
 def _make_view(self, sdfg: SDFG, graph: SDFGState,
                in_array: nodes.AccessNode, out_array: nodes.AccessNode,
                e1: graph.MultiConnectorEdge[mm.Memlet],
                b_subset: subsets.Subset, b_dims_to_pop: typing.List[int]):
     in_desc = sdfg.arrays[in_array.data]
     out_desc = sdfg.arrays[out_array.data]
     # NOTE: We do not want to create another view, if the immediate
     # ancestors of in_array are views as well. We just remove it.
     in_ancestors_desc = [
         e.src.desc(sdfg) if isinstance(e.src, nodes.AccessNode) else None
         for e in graph.in_edges(in_array)
     ]
     if all([
             desc and isinstance(desc, data.View)
             for desc in in_ancestors_desc
     ]):
         for e in graph.in_edges(in_array):
             a_subset, _ = _validate_subsets(e, sdfg.arrays)
             graph.add_edge(
                 e.src, e.src_conn, out_array, None,
                 mm.Memlet(out_array.data,
                           subset=b_subset,
                           other_subset=a_subset,
                           wcr=e1.data.wcr,
                           wcr_nonatomic=e1.data.wcr_nonatomic))
             graph.remove_edge(e)
         graph.remove_edge(e1)
         graph.remove_node(in_array)
         if in_array.data in sdfg.arrays:
             del sdfg.arrays[in_array.data]
         return
     view_strides = in_desc.strides
     if (b_dims_to_pop and len(b_dims_to_pop)
             == len(out_desc.shape) - len(in_desc.shape)):
         view_strides = [
             s for i, s in enumerate(out_desc.strides)
             if i not in b_dims_to_pop
         ]
     sdfg.arrays[in_array.data] = data.View(
         in_desc.dtype, in_desc.shape, True, in_desc.allow_conflicts,
         out_desc.storage, out_desc.location, view_strides, in_desc.offset,
         out_desc.may_alias, dtypes.AllocationLifetime.Scope,
         in_desc.alignment, in_desc.debuginfo, in_desc.total_size)
コード例 #4
0
ファイル: redundant_array.py プロジェクト: andreaskuster/dace
    def apply(self, sdfg):
        def gnode(nname):
            return graph.nodes()[self.subgraph[nname]]

        graph = sdfg.nodes()[self.state_id]
        in_array = self.in_array(sdfg)
        out_array = self.out_array(sdfg)
        in_desc = sdfg.arrays[in_array.data]
        out_desc = sdfg.arrays[out_array.data]

        # If arrays are not of the same shape, modify first array to reshape
        # instead of removing it
        if len(in_desc.shape) != len(out_desc.shape) or any(
                i != o for i, o in zip(in_desc.shape, out_desc.shape)):
            sdfg.arrays[in_array.data] = data.View(
                in_desc.dtype, in_desc.shape, True, in_desc.allow_conflicts,
                out_desc.storage, out_desc.location, in_desc.strides,
                in_desc.offset, out_desc.may_alias, out_desc.lifetime,
                in_desc.alignment, in_desc.debuginfo, in_desc.total_size)
            return

        for e in graph.in_edges(in_array):
            # Modify all incoming edges to point to out_array
            path = graph.memlet_path(e)
            for pe in path:
                if pe.data.data == in_array.data:
                    pe.data.data = out_array.data

            # Redirect edge to out_array
            graph.remove_edge(e)
            graph.add_edge(e.src, e.src_conn, out_array, e.dst_conn, e.data)

        # Finally, remove in_array node
        graph.remove_node(in_array)
        if in_array.data in sdfg.arrays:
            del sdfg.arrays[in_array.data]
コード例 #5
0
ファイル: reduce.py プロジェクト: fthaler/dace
    def redirect_edge(graph,
                      edge,
                      new_src=None,
                      new_src_conn=None,
                      new_dst=None,
                      new_dst_conn=None,
                      new_data=None):

        data = new_data if new_data else edge.data
        if new_src and new_dst:
            ret = graph.add_edge(new_src, new_src_conn, new_dst, new_dst_conn,
                                 data)
            graph.remove_edge(edge)
        elif new_src:
            ret = graph.add_edge(new_src, new_src_conn, edge.dst,
                                 edge.dst_conn, data)
            graph.remove_edge(edge)
        elif new_dst:
            ret = graph.add_edge(edge.src, edge.src_conn, new_dst,
                                 new_dst_conn, data)
            graph.remove_edge(edge)
        else:
            pass
        return ret
コード例 #6
0
ファイル: redundant_array.py プロジェクト: thobauma/dace
    def apply(self, sdfg):
        def gnode(nname):
            return graph.nodes()[self.subgraph[nname]]

        graph = sdfg.nodes()[self.state_id]
        in_array = gnode(RedundantSecondArray._in_array)
        out_array = gnode(RedundantSecondArray._out_array)
        in_desc = sdfg.arrays[in_array.data]
        out_desc = sdfg.arrays[out_array.data]

        # We assume the following pattern: A -- e1 --> B -- e2 --> others

        # 1. Get edge e1 and extract subsets for arrays A and B
        e1 = graph.edges_between(in_array, out_array)[0]
        a_subset, b1_subset = _validate_subsets(e1, sdfg.arrays)

        # Find extraneous A or B subset dimensions
        a_dims_to_pop = []
        b_dims_to_pop = []
        aset = a_subset
        popped = []
        if a_subset and b1_subset and a_subset.dims() != b1_subset.dims():
            a_size = a_subset.size_exact()
            b_size = b1_subset.size_exact()
            if a_subset.dims() > b1_subset.dims():
                a_dims_to_pop = find_dims_to_pop(a_size, b_size)
                aset, popped = pop_dims(a_subset, a_dims_to_pop)
            else:
                b_dims_to_pop = find_dims_to_pop(b_size, a_size)

        # If the src subset does not cover the removed array, create a view.
        if a_subset and any(m != a
                            for m, a in zip(a_subset.size(), out_desc.shape)):
            # NOTE: We do not want to create another view, if the immediate
            # successors of out_array are views as well. We just remove it.
            out_successors_desc = [
                e.dst.desc(sdfg)
                if isinstance(e.dst, nodes.AccessNode) else None
                for e in graph.out_edges(out_array)
            ]
            if all([
                    desc and isinstance(desc, data.View)
                    for desc in out_successors_desc
            ]):
                for e in graph.out_edges(out_array):
                    _, b_subset = _validate_subsets(e, sdfg.arrays)
                    graph.add_edge(
                        in_array, None, e.dst, e.dst_conn,
                        mm.Memlet(in_array.data,
                                  subset=a_subset,
                                  other_subset=b_subset,
                                  wcr=e1.data.wcr,
                                  wcr_nonatomic=e1.data.wcr_nonatomic))
                    graph.remove_edge(e)
                graph.remove_edge(e1)
                graph.remove_node(out_array)
                if out_array.data in sdfg.arrays:
                    del sdfg.arrays[out_array.data]
                return
            view_strides = out_desc.strides
            if (a_dims_to_pop and len(a_dims_to_pop)
                    == len(in_desc.shape) - len(out_desc.shape)):
                view_strides = [
                    s for i, s in enumerate(in_desc.strides)
                    if i not in a_dims_to_pop
                ]
            sdfg.arrays[out_array.data] = data.View(
                out_desc.dtype, out_desc.shape, True, out_desc.allow_conflicts,
                in_desc.storage, in_desc.location, view_strides,
                out_desc.offset, in_desc.may_alias,
                dtypes.AllocationLifetime.Scope, out_desc.alignment,
                out_desc.debuginfo, out_desc.total_size)
            return

        # 2. Iterate over the e2 edges and traverse the memlet tree
        for e2 in graph.out_edges(out_array):
            path = graph.memlet_tree(e2)
            wcr = e1.data.wcr
            wcr_nonatomic = e1.data.wcr_nonatomic
            for e3 in path:
                # 2-a. Extract subsets for array B and others
                b3_subset, other_subset = _validate_subsets(
                    e3, sdfg.arrays, src_name=out_array.data)
                # 2-b. Modify memlet to match array A. Example:
                # A -- (0, a:b)/(c:c+b) --> B -- (c+d)/None --> others
                # A -- (0, a+d)/None --> others
                e3.data.data = in_array.data
                # (c+d) - (c:c+b) = (d)
                b3_subset.offset(b1_subset, negative=True)
                # (0, a:b)(d) = (0, a+d) (or offset for indices)

                if b3_subset and b_dims_to_pop:
                    bset, _ = pop_dims(b3_subset, b_dims_to_pop)
                else:
                    bset = b3_subset

                e3.data.subset = compose_and_push_back(aset, bset,
                                                       a_dims_to_pop, popped)
                # NOTE: This fixes the following case:
                # A ----> A[subset] ----> ... -----> Tasklet
                # Tasklet is not data, so it doesn't have an other subset.
                if isinstance(e3.dst, nodes.AccessNode):
                    e3.data.other_subset = other_subset
                else:
                    e3.data.other_subset = None
                wcr = wcr or e3.data.wcr
                wcr_nonatomic = wcr_nonatomic or e3.data.wcr_nonatomic
                e3.data.wcr = wcr
                e3.data.wcr_nonatomic = wcr_nonatomic

            # 2-c. Remove edge and add new one
            graph.remove_edge(e2)
            e2.data.wcr = wcr
            e2.data.wcr_nonatomic = wcr_nonatomic
            graph.add_edge(in_array, e2.src_conn, e2.dst, e2.dst_conn, e2.data)

        # Finally, remove out_array node
        graph.remove_node(out_array)
        if out_array.data in sdfg.arrays:
            try:
                sdfg.remove_data(out_array.data)
            except ValueError:  # Already in use (e.g., with Views)
                pass
コード例 #7
0
ファイル: redundant_array.py プロジェクト: thobauma/dace
    def apply(self, sdfg):
        graph = sdfg.nodes()[self.state_id]
        in_array = self.in_array(sdfg)
        out_array = self.out_array(sdfg)
        in_desc = sdfg.arrays[in_array.data]
        out_desc = sdfg.arrays[out_array.data]

        # 1. Get edge e1 and extract subsets for arrays A and B
        e1 = graph.edges_between(in_array, out_array)[0]
        a1_subset, b_subset = _validate_subsets(e1, sdfg.arrays)

        # View connected to a view: simple case
        if (isinstance(in_desc, data.View)
                and isinstance(out_desc, data.View)):
            for e in graph.in_edges(in_array):
                new_memlet = copy.deepcopy(e.data)
                e.dst_subset = b_subset
                graph.add_edge(e.src, e.src_conn, out_array, e.dst_conn,
                               new_memlet)
            graph.remove_node(in_array)
            if in_array.data in sdfg.arrays:
                del sdfg.arrays[in_array.data]
            return

        # Find extraneous A or B subset dimensions
        a_dims_to_pop = []
        b_dims_to_pop = []
        bset = b_subset
        popped = []
        if a1_subset and b_subset and a1_subset.dims() != b_subset.dims():
            a_size = a1_subset.size_exact()
            b_size = b_subset.size_exact()
            if a1_subset.dims() > b_subset.dims():
                a_dims_to_pop = find_dims_to_pop(a_size, b_size)
            else:
                b_dims_to_pop = find_dims_to_pop(b_size, a_size)
                bset, popped = pop_dims(b_subset, b_dims_to_pop)

        from dace.libraries.standard import Reduce
        reduction = False
        for e in graph.in_edges(in_array):
            if isinstance(e.src, Reduce):
                reduction = True

        # If:
        # 1. A reduce node is involved;
        # 2. The memlet does not cover the removed array; or
        # 3. Dimensions are mismatching (all dimensions are popped);
        # create a view.
        if reduction or len(a_dims_to_pop) == len(in_desc.shape) or any(
                m != a for m, a in zip(a1_subset.size(), in_desc.shape)):
            self._make_view(sdfg, graph, in_array, out_array, e1, b_subset,
                            b_dims_to_pop)
            return

        # Validate that subsets are composable. If not, make a view
        try:
            for e2 in graph.in_edges(in_array):
                path = graph.memlet_tree(e2)
                wcr = e1.data.wcr
                wcr_nonatomic = e1.data.wcr_nonatomic
                for e3 in path:
                    # 2-a. Extract subsets for array B and others
                    other_subset, a3_subset = _validate_subsets(
                        e3, sdfg.arrays, dst_name=in_array.data)
                    # 2-b. Modify memlet to match array B.
                    dname = out_array.data
                    src_is_data = False
                    a3_subset.offset(a1_subset, negative=True)

                    if a3_subset and a_dims_to_pop:
                        aset, _ = pop_dims(a3_subset, a_dims_to_pop)
                    else:
                        aset = a3_subset

                    compose_and_push_back(bset, aset, b_dims_to_pop, popped)
        except (ValueError, NotImplementedError):
            self._make_view(sdfg, graph, in_array, out_array, e1, b_subset,
                            b_dims_to_pop)
            return

        # 2. Iterate over the e2 edges and traverse the memlet tree
        for e2 in graph.in_edges(in_array):
            path = graph.memlet_tree(e2)
            wcr = e1.data.wcr
            wcr_nonatomic = e1.data.wcr_nonatomic
            for e3 in path:
                # 2-a. Extract subsets for array B and others
                other_subset, a3_subset = _validate_subsets(
                    e3, sdfg.arrays, dst_name=in_array.data)
                # 2-b. Modify memlet to match array B.
                dname = out_array.data
                src_is_data = False
                a3_subset.offset(a1_subset, negative=True)

                if a3_subset and a_dims_to_pop:
                    aset, _ = pop_dims(a3_subset, a_dims_to_pop)
                else:
                    aset = a3_subset

                dst_subset = compose_and_push_back(bset, aset, b_dims_to_pop,
                                                   popped)
                # NOTE: This fixes the following case:
                # Tasklet ----> A[subset] ----> ... -----> A
                # Tasklet is not data, so it doesn't have an other subset.
                if isinstance(e3.src, nodes.AccessNode):
                    if e3.src.data == out_array.data:
                        dname = e3.src.data
                        src_is_data = True
                    src_subset = other_subset
                else:
                    src_subset = None

                subset = src_subset if src_is_data else dst_subset
                other_subset = dst_subset if src_is_data else src_subset
                e3.data.data = dname
                e3.data.subset = subset
                e3.data.other_subset = other_subset
                wcr = wcr or e3.data.wcr
                wcr_nonatomic = wcr_nonatomic or e3.data.wcr_nonatomic
                e3.data.wcr = wcr
                e3.data.wcr_nonatomic = wcr_nonatomic

            # 2-c. Remove edge and add new one
            graph.remove_edge(e2)
            e2.data.wcr = wcr
            e2.data.wcr_nonatomic = wcr_nonatomic
            graph.add_edge(e2.src, e2.src_conn, out_array, e2.dst_conn,
                           e2.data)

        # Finally, remove in_array node
        graph.remove_node(in_array)
        try:
            if in_array.data in sdfg.arrays:
                sdfg.remove_data(in_array.data)
        except ValueError:  # Already in use (e.g., with Views)
            pass
コード例 #8
0
ファイル: redundant_array.py プロジェクト: xiacijie/dace
    def apply(self, sdfg):
        graph = sdfg.nodes()[self.state_id]
        in_array = self.in_array(sdfg)
        out_array = self.out_array(sdfg)
        in_desc = sdfg.arrays[in_array.data]
        out_desc = sdfg.arrays[out_array.data]

        # 1. Get edge e1 and extract subsets for arrays A and B
        e1 = graph.edges_between(in_array, out_array)[0]
        a1_subset, b_subset = _validate_subsets(e1, sdfg.arrays)

        # Find extraneous A or B subset dimensions
        a_dims_to_pop = []
        b_dims_to_pop = []
        bset = b_subset
        popped = []
        if a1_subset and b_subset and a1_subset.dims() != b_subset.dims():
            a_size = a1_subset.size_exact()
            b_size = b_subset.size_exact()
            if a1_subset.dims() > b_subset.dims():
                a_dims_to_pop = find_dims_to_pop(a_size, b_size)
            else:
                b_dims_to_pop = find_dims_to_pop(b_size, a_size)
                bset, popped = pop_dims(b_subset, b_dims_to_pop)

        from dace.libraries.standard import Reduce
        reduction = False
        for e in graph.in_edges(in_array):
            if isinstance(e.src, Reduce):
                reduction = True

        # If the memlet does not cover the removed array, create a view.
        if reduction or any(m != a
                            for m, a in zip(a1_subset.size(), in_desc.shape)):
            # NOTE: We do not want to create another view, if the immediate
            # ancestors of in_array are views as well. We just remove it.
            in_ancestors_desc = [
                e.src.desc(sdfg)
                if isinstance(e.src, nodes.AccessNode) else None
                for e in graph.in_edges(in_array)
            ]
            if all([
                    desc and isinstance(desc, data.View)
                    for desc in in_ancestors_desc
            ]):
                for e in graph.in_edges(in_array):
                    a_subset, _ = _validate_subsets(e, sdfg.arrays)
                    graph.add_edge(
                        e.src, e.src_conn, out_array, None,
                        mm.Memlet(out_array.data,
                                  subset=b_subset,
                                  other_subset=a_subset,
                                  wcr=e1.data.wcr,
                                  wcr_nonatomic=e1.data.wcr.nonatomic))
                    graph.remove_edge(e)
                graph.remove_edge(e1)
                graph.remove_node(in_array)
                if in_array.data in sdfg.arrays:
                    del sdfg.arrays[in_array.data]
                return
            view_strides = in_desc.strides
            if (b_dims_to_pop and len(b_dims_to_pop)
                    == len(out_desc.shape) - len(in_desc.shape)):
                view_strides = [
                    s for i, s in enumerate(out_desc.strides)
                    if i not in b_dims_to_pop
                ]
            sdfg.arrays[in_array.data] = data.View(
                in_desc.dtype, in_desc.shape, True, in_desc.allow_conflicts,
                out_desc.storage, out_desc.location, view_strides,
                in_desc.offset, out_desc.may_alias,
                dtypes.AllocationLifetime.Scope, in_desc.alignment,
                in_desc.debuginfo, in_desc.total_size)
            return

        # 2. Iterate over the e2 edges and traverse the memlet tree
        for e2 in graph.in_edges(in_array):
            path = graph.memlet_tree(e2)
            wcr = e1.data.wcr
            wcr_nonatomic = e1.data.wcr_nonatomic
            for e3 in path:
                # 2-a. Extract subsets for array B and others
                other_subset, a3_subset = _validate_subsets(
                    e3, sdfg.arrays, dst_name=in_array.data)
                # 2-b. Modify memlet to match array B.
                dname = out_array.data
                src_is_data = False
                a3_subset.offset(a1_subset, negative=True)

                if a3_subset and a_dims_to_pop:
                    aset, _ = pop_dims(a3_subset, a_dims_to_pop)
                else:
                    aset = a3_subset

                dst_subset = compose_and_push_back(bset, aset, b_dims_to_pop,
                                                   popped)
                # NOTE: This fixes the following case:
                # Tasklet ----> A[subset] ----> ... -----> A
                # Tasklet is not data, so it doesn't have an other subset.
                if isinstance(e3.src, nodes.AccessNode):
                    if e3.src.data == out_array.data:
                        dname = e3.src.data
                        src_is_data = True
                    src_subset = other_subset
                else:
                    src_subset = None

                subset = src_subset if src_is_data else dst_subset
                other_subset = dst_subset if src_is_data else src_subset
                e3.data.data = dname
                e3.data.subset = subset
                e3.data.other_subset = other_subset
                wcr = wcr or e3.data.wcr
                wcr_nonatomic = wcr_nonatomic or e3.data.wcr_nonatomic
                e3.data.wcr = wcr
                e3.data.wcr_nonatomic = wcr_nonatomic

            # 2-c. Remove edge and add new one
            graph.remove_edge(e2)
            e2.data.wcr = wcr
            e2.data.wcr_nonatomic = wcr_nonatomic
            graph.add_edge(e2.src, e2.src_conn, out_array, e2.dst_conn, e2.data)

        # Finally, remove in_array node
        graph.remove_node(in_array)
        if in_array.data in sdfg.arrays:
            del sdfg.arrays[in_array.data]