예제 #1
0
파일: papi.py 프로젝트: mfkiwl/dace
    def get_out_memlet_costs(sdfg: dace.SDFG, state_id: int, node: nodes.Node,
                             dfg: StateGraphView):
        scope_dict = sdfg.node(state_id).scope_dict()

        out_costs = 0
        for edge in dfg.out_edges(node):
            _, uconn, v, _, memlet = edge
            dst_node = dfg.memlet_path(edge)[-1].dst

            if (isinstance(node, nodes.CodeNode)
                    and isinstance(dst_node, nodes.AccessNode)):

                # If the memlet is pointing into an array in an inner scope,
                # it will be handled by the inner scope.
                if (scope_dict[node] != scope_dict[dst_node]
                        and scope_contains_scope(scope_dict, node, dst_node)):
                    continue

                if not uconn:
                    # This would normally raise a syntax error
                    return 0

                if memlet.subset.data_dims() == 0:
                    if memlet.wcr is not None:
                        # write_and_resolve
                        # We have to assume that every reduction costs 3
                        # accesses of the same size (read old, read new, write)
                        out_costs += 3 * PAPIUtils.get_memlet_byte_size(
                            sdfg, memlet)
                    else:
                        # This standard operation is already counted
                        out_costs += PAPIUtils.get_memlet_byte_size(
                            sdfg, memlet)
        return out_costs
예제 #2
0
    def apply(self, sdfg):
        graph = sdfg.nodes()[self.state_id]
        node_a = self.node_a(sdfg)
        node_b = self.node_b(sdfg)

        # Determine direction of new memlet
        scope_dict = graph.scope_dict()
        propagate_forward = sd.scope_contains_scope(scope_dict, node_a, node_b)

        array = self.array
        if array is None or len(array) == 0:
            array = next(e.data.data
                         for e in graph.edges_between(node_a, node_b)
                         if e.data.data is not None and e.data.wcr is None)

        original_edge = None
        invariant_memlet = None
        for edge in graph.edges_between(node_a, node_b):
            if array == edge.data.data:
                original_edge = edge
                invariant_memlet = edge.data
                break
        if invariant_memlet is None:
            for edge in graph.edges_between(node_a, node_b):
                original_edge = edge
                invariant_memlet = edge.data
                warnings.warn('Array %s not found! Using array %s instead.' %
                              (array, invariant_memlet.data))
                array = invariant_memlet.data
                break
        if invariant_memlet is None:
            raise NameError('Array %s not found!' % array)

        # Add transient array
        new_data, _ = sdfg.add_array('trans_' + invariant_memlet.data, [
            symbolic.overapproximate(r)
            for r in invariant_memlet.bounding_box_size()
        ],
                                     sdfg.arrays[invariant_memlet.data].dtype,
                                     transient=True,
                                     find_new_name=True)
        data_node = nodes.AccessNode(new_data)

        # Store as fields so that other transformations can use them
        self._local_name = new_data
        self._data_node = data_node

        to_data_mm = copy.deepcopy(invariant_memlet)
        from_data_mm = copy.deepcopy(invariant_memlet)
        offset = subsets.Indices([r[0] for r in invariant_memlet.subset])

        # Reconnect, assuming one edge to the access node
        graph.remove_edge(original_edge)
        if propagate_forward:
            graph.add_edge(node_a, original_edge.src_conn, data_node, None,
                           to_data_mm)
            new_edge = graph.add_edge(data_node, None, node_b,
                                      original_edge.dst_conn, from_data_mm)
        else:
            new_edge = graph.add_edge(node_a, original_edge.src_conn,
                                      data_node, None, to_data_mm)
            graph.add_edge(data_node, None, node_b, original_edge.dst_conn,
                           from_data_mm)

        # Offset all edges in the memlet tree (including the new edge)
        for edge in graph.memlet_tree(new_edge):
            edge.data.subset.offset(offset, True)
            edge.data.data = new_data

        return data_node