Пример #1
0
def retrieve_iteration_tree(node, mode='normal'):
    """Return a list of all :class:`Iteration` sub-trees rooted in ``node``.
    For example, given the Iteration tree:

        .. code-block:: c

           Iteration i
             expr0
             Iteration j
               Iteraion k
                 expr1
             Iteration p
               expr2

    Return the list: ::

        [(Iteration i, Iteration j, Iteration k), (Iteration i, Iteration p)]

    :param node: The searched Iteration/Expression tree.
    :param mode: Accepted values are 'normal' (default) and 'superset', in which
                 case iteration trees that are subset of larger iteration trees
                 are dropped.
    """
    assert mode in ('normal', 'superset')

    trees = [i for i in FindSections().visit(node) if i]
    if mode == 'normal':
        return trees
    else:
        match = []
        for i in trees:
            if any(set(i).issubset(set(j)) for j in trees if i != j):
                continue
            match.append(i)
        return match
Пример #2
0
def analyze_iterations(nodes):
    """
    Attach :class:`IterationProperty` to :class:`Iteration` objects within
    ``nodes``. The recognized IterationProperty decorators are listed in
    ``nodes.IterationProperty._KNOWN``.
    """
    sections = FindSections().visit(nodes)

    # Local analysis: detect Iteration properties, inspecting trees in isolation
    mapper = OrderedDict()
    for tree, exprs in sections.items():
        deps_graph = compute_dependency_graph(exprs)

        mapper = detect_fully_parallel(tree, deps_graph, mapper)
        mapper = detect_outermost_parallel(tree, deps_graph, mapper)
        mapper = detect_outermost_sequential_inner_parallel(
            tree, deps_graph, mapper)
        mapper = detect_innermost_unitstride(tree, deps_graph, mapper)
        mapper = detect_wrappable_iterations(tree, deps_graph, mapper)

    # Global analysis
    for k, v in list(mapper.items()):
        args = k.args
        # SEQUENTIAL kills PARALLEL
        properties = [i for i in v if i != PARALLEL] if SEQUENTIAL in v else v
        properties = as_tuple(args.pop('properties')) + as_tuple(properties)
        mapper[k] = Iteration(properties=properties, **args)

    # Store the discovered properties in the Iteration/Expression tree
    processed = NestedTransformer(mapper).visit(nodes)

    return processed
Пример #3
0
def test_find_sections(exprs, block1, block2, block3):
    finder = FindSections()

    sections = finder.visit(block1)
    assert len(sections) == 1

    sections = finder.visit(block2)
    assert len(sections) == 2
    found = list(sections.values())
    assert len(found[0]) == 1
    assert len(found[1]) == 1

    sections = finder.visit(block3)
    assert len(sections) == 3
    found = list(sections.values())
    assert len(found[0]) == 1
    assert len(found[1]) == 2
    assert len(found[2]) == 1
Пример #4
0
def retrieve_iteration_tree(node, mode='normal'):
    """
    A list with all :class:`Iteration` sub-trees within an IET.

    Examples
    --------
    Given the Iteration tree:

        .. code-block:: c

           Iteration i
             expr0
             Iteration j
               Iteraion k
                 expr1
             Iteration p
               expr2

    Return the list: ::

        [(Iteration i, Iteration j, Iteration k), (Iteration i, Iteration p)]

    Parameters
    ----------
    iet : Node
        The searched Iteration/Expression tree.
    mode : str, optional
        - ``normal``
        - ``superset``: Iteration trees that are subset of larger iteration trees
                        are dropped.
    """
    assert mode in ('normal', 'superset')

    trees = [IterationTree(i) for i in FindSections().visit(node) if i]
    if mode == 'normal':
        return trees
    else:
        match = []
        for i in trees:
            if any(set(i).issubset(set(j)) for j in trees if i != j):
                continue
            match.append(i)
        return IterationTree(match)
Пример #5
0
def create_profile(node):
    """
    Create a :class:`Profiler` for the Iteration/Expression tree ``node``.
    The following code sections are profiled: ::

        * The whole ``node``;
        * A sequence of perfectly nested loops that have common :class:`Iteration`
          dimensions, but possibly different extent. For example: ::

            for x = 0 to N
              ..
            for x = 1 to N-1
              ..

          Both Iterations have dimension ``x``, and will be profiled as a single
          section, though their extent is different.
        * Any perfectly nested loops.
    """
    profiler = Profiler()

    # Group by root Iteration
    mapper = OrderedDict()
    for itspace in FindSections().visit(node):
        mapper.setdefault(itspace[0], []).append(itspace)

    # Group sections if their iteration spaces overlap
    key = lambda itspace: set([i.dim for i in itspace])
    found = []
    for v in mapper.values():
        queue = list(v)
        handle = []
        while queue:
            item = queue.pop(0)
            if not handle or key(item) == key(handle[0]):
                handle.append(item)
            else:
                # Found a timing section
                found.append(tuple(handle))
                handle = [item]
        if handle:
            found.append(tuple(handle))

    # Create and track C-level timers
    mapper = OrderedDict()
    for i, group in enumerate(found):
        name = 'section_%d' % i

        # We time at the single timestep level
        for i in zip(*group):
            root = i[0]
            remainder = tuple(j for j in i if j is not root)
            if not (root.dim.is_Time or root.dim.is_Stepping):
                break

        # Prepare to transform the Iteration/Expression tree
        body = (root, ) + remainder
        mapper[root] = TimedList(gname=profiler.varname, lname=name, body=body)
        mapper.update(OrderedDict([(j, None) for j in remainder]))

        # Estimate computational properties of the profiled section
        expressions = FindNodes(Expression).visit(body)
        ops = estimate_cost([e.expr for e in expressions])
        memory = estimate_memory([e.expr for e in expressions])

        # Keep track of the new profiled section
        profiler.add(name, group[0], ops, memory)

    # Transform the Iteration/Expression tree introducing the C-level timers
    processed = Transformer(mapper).visit(node)

    return processed, profiler