[Mesa-dev] [PATCH 1/4] glapi/gen: Create optimized glX opcode dispatch tree

Matt Turner mattst88 at gmail.com
Sun Mar 3 22:19:14 PST 2013


Some spelling fixes:

On Sun, Mar 3, 2013 at 4:41 PM, Stefan Brüns
<stefan.bruens at rwth-aachen.de> wrote:
> The current code omits some possibilities to optimize the tree, leading
> to a large tree with way to many steps until the leave is reached.

Singular of leaves is leaf.

> The new code optimizes the tree based on a simple observation: as long
> as at most half of the nodes at the current level are leaves, tree size
> is reduced or kept when the children are pulled up one level.
>
> Tree depth is halved on average (for some leaves, reduced from 9 to 3),
> tree size is reduced slightly.
>
> The algorithm works as follows:
> 1. create leaves, each containing min_op_count opcodes
> 2. create a binary tree
> 3. pullup children, as long as there are children and tree size is reduced
> 3.1. do the same for each non-leave child

leaf

> The pullup algorithm has one tunable, "pullup_bias". If set to 0, the
> algorithm is followed stritly, if set to values larger 0, some more

strictly

> children are pulled up, reducing depth in favor of slightly increased size.
>
> Signed-off-by: Stefan Brüns <stefan.bruens at rwth-aachen.de>
> ---
>  src/mapi/glapi/gen/glX_server_table.py |   76
> ++++++++++++++++++++++++++++++++
>  1 file changed, 76 insertions(+)
>
> diff --git a/src/mapi/glapi/gen/glX_server_table.py
> b/src/mapi/glapi/gen/glX_server_table.py
> index 47aa111..5b3ffdc 100644
> --- a/src/mapi/glapi/gen/glX_server_table.py
> +++ b/src/mapi/glapi/gen/glX_server_table.py
> @@ -65,6 +65,8 @@ class function_table:
>          # Minimum number of opcodes in a leaf node.
>          self.min_op_bits = 3
>          self.min_op_count = (1 << self.min_op_bits)
> +
> +        self.pullup_bias = 1
>          return
>
>
> @@ -84,6 +86,80 @@ class function_table:
>          return
>
>
> +    def get_leaves(self):
> +        leaves = []
> +
> +        for i in range(0, (1<<self.max_bits), self.min_op_count):
> +
> +            # M, [children], tree size, depth, type, first opcode
> +            leave = [ 0, [], 1, 0, 'E', i ]

leaf

> +
> +            for j in range(i, i + self.min_op_count):
> +                if self.functions.has_key(j):
> +                    leave[4] = 'L'
> +                    break;
> +
> +            leaves.append(leave)
> +
> +        return leaves
> +
> +
> +    def combine_tree(self, nodes):
> +        newnodes = []
> +
> +        for i in range(0, len(nodes)-1, 2):
> +            c1 = nodes[i]
> +            c2 = nodes[i+1]
> +            parent = [ 1, [c1, c2], c1[2]+c2[2]+1, 0, 'N', c1[5] ]
> +            if c1[4] == c2[4]:
> +                parent[4] = c1[4]
> +
> +            newnodes.append(parent)
> +
> +        if len(newnodes) >= 2:
> +            return self.combine_tree(newnodes)
> +
> +        return parent
> +
> +
> +    def pullup_nodes(self, node):
> +
> +        children = node[1]
> +
> +        # Count non-leaves. If at least half of the children
> +        # are non-leaves pulling up saves space. Add a small
> +        # bias to favor shallower trees
> +        count = sum( 1 for child in children if child[4] == 'N' )
> +        count += self.pullup_bias
> +
> +        # conditionally replace the children of a node with its
> +        # grandchilren. Grandchildren exist if child size > 1

grandchildren

> +        if count >= len(children)/2 and children[0][2] > 1:
> +            newnodes = []
> +            for child in children:
> +                newnodes.append(child[1][0])
> +                newnodes.append(child[1][1])
> +
> +            node[0] += 1
> +            node[1] = newnodes
> +            node[2] = newnodes[0][2] * len(newnodes) + 1
> +            self.pullup_nodes(node)
> +
> +        else:
> +            node[2] = 1
> +            for child in children:
> +                if child[4] == 'N':
> +                    self.pullup_nodes(child)
> +                else:
> +                    child[1] = []
> +                    child[2] = 1
> +
> +                node[3] = max( child[3] + 1, node[3] )
> +                node[2] += child[2]
> +
> +        return
> +
> +
>      def divide_group(self, min_opcode, total):
>          """Divide the group starting min_opcode into subgroups.
>          Returns a tuple containing the number of bits consumed by
> --
> 1.7.10.4


More information about the mesa-dev mailing list