Beispiel #1
0
        /// <summary>
        /// Collect statements that need to re-execute due to initialization.
        /// </summary>
        /// <param name="blocks"></param>
        /// <param name="dependencyGraph"></param>
        /// <param name="stmts"></param>
        /// <param name="nodesToMove">Modified on exit</param>
        private Dictionary <Loop, IBlockStatement> GetFirstIterPostprocessing(List <StatementBlock> blocks, DirectedGraphFilter <NodeIndex, EdgeIndex> dependencyGraph, IList <IStatement> stmts, ICollection <NodeIndex> nodesToMove)
        {
            var hasUserInitializedAncestor            = dependencyGraph.CreateNodeData(false);
            DepthFirstSearch <NodeIndex> dfsInitBlock = new DepthFirstSearch <int>(dependencyGraph.SourcesOf, dependencyGraph);
            List <NodeIndex>             nodesToRerun = new List <NodeIndex>();

            dfsInitBlock.FinishNode += delegate(NodeIndex node)
            {
                var stmt = stmts[node];
                if (SchedulingTransform.IsUserInitialized(context, stmt))
                {
                    // do nothing
                }
                else if (SchedulingTransform.HasUserInitializedInitializer(context, stmt))
                {
                    hasUserInitializedAncestor[node] = true;
                    nodesToMove.Add(node);
                    nodesToRerun.Add(node);
                }
                else
                {
                    var inherit = dependencyGraph.SourcesOf(node).Any(source => hasUserInitializedAncestor[source]);
                    if (inherit)
                    {
                        hasUserInitializedAncestor[node] = true;
                        nodesToRerun.Add(node);
                    }
                }
            };
            Dictionary <Loop, IBlockStatement> firstIterPostprocessing = new Dictionary <Loop, IBlockStatement>();

            foreach (StatementBlock block in blocks)
            {
                if (block is Loop)
                {
                    Loop loop = (Loop)block;
                    // find the set of initialized nodes that are ancestors of the loop (and not ancestors of an ancestor loop)
                    // find all nodes that are ancestors of the loop and descendants of (and including) the init nodes - cannot contain any loops
                    // because we do not clear dfs, all previous stmts in loops are excluded.
                    dfsInitBlock.SearchFrom(loop.indices);
                    foreach (var i in loop.indices)
                    {
                        nodesToMove.Remove(i);
                        nodesToRerun.Remove(i);
                    }
                    if (nodesToRerun.Count > 0)
                    {
                        var firstIterPost = Builder.BlockStmt();
                        foreach (var node in nodesToRerun)
                        {
                            IStatement stmt = stmts[node];
                            if (nodesToMove.Contains(node))
                            {
                                firstIterPost.Statements.Add(stmt);
                            }
                            else
                            {
                                // clone the statement
                                this.ShallowCopy = true;
                                var convertedStmt = ConvertStatement(stmt);
                                this.ShallowCopy = false;
                                firstIterPost.Statements.Add(convertedStmt);
                                loopMergingInfo.AddEquivalentStatement(convertedStmt, loopMergingInfo.GetIndexOf(stmt));
                                clonesOfStatement.Add(stmt, new List <IStatement>()
                                {
                                    convertedStmt
                                });
                            }
                        }
                        firstIterPostprocessing.Add(loop, firstIterPost);
                        nodesToRerun.Clear();
                    }
                }
            }
            return(firstIterPostprocessing);
        }
Beispiel #2
0
        private List <IStatement> Schedule(DependencyGraph g, IList <IStatement> stmts, bool createFirstIterPostBlocks)
        {
            List <IStatement>     output       = new List <IStatement>();
            List <StatementBlock> blocks       = new List <StatementBlock>();
            List <NodeIndex>      currentBlock = null;
            DirectedGraphFilter <NodeIndex, EdgeIndex> graph2 = new DirectedGraphFilter <NodeIndex, EdgeIndex>(g.dependencyGraph, edge => !g.isDeleted[edge]);
            StrongComponents2 <NodeIndex> scc = new StrongComponents2 <NodeIndex>(graph2.SourcesOf, graph2);

            scc.AddNode        += delegate(NodeIndex node) { currentBlock.Add(node); };
            scc.BeginComponent += delegate() { currentBlock = new List <int>(); };
            scc.EndComponent   += delegate() {
                bool isCyclic = false;
                if (currentBlock.Count == 1)
                {
                    NodeIndex node = currentBlock[0];
                    foreach (NodeIndex source in graph2.SourcesOf(node))
                    {
                        if (source == node)
                        {
                            isCyclic = true;
                            break;
                        }
                    }
                }
                else
                {
                    isCyclic = true;
                }
                if (isCyclic)
                {
                    blocks.Add(new Loop()
                    {
                        indices = currentBlock
                    });
                }
                else
                {
                    blocks.Add(new StraightLine()
                    {
                        indices = currentBlock
                    });
                }
            };
            scc.SearchFrom(graph2.Nodes);
            //scc.SearchFrom(g.outputNodes);

            bool check = false;

            if (check)
            {
                // check that there are no edges from a later component to an earlier component
                Set <NodeIndex> earlierNodes = new Set <int>();
                foreach (StatementBlock block in blocks)
                {
                    earlierNodes.AddRange(block.indices);
                    foreach (NodeIndex node in block.indices)
                    {
                        foreach (NodeIndex source in graph2.SourcesOf(node))
                        {
                            if (!earlierNodes.Contains(source))
                            {
                                Console.WriteLine(g.NodeToString(node) + Environment.NewLine + "   depends on later node " + g.NodeToString(source));
                                Error("Internal error: Strong components are not ordered properly");
                            }
                        }
                    }
                }
            }

            Set <NodeIndex> nodesToMove = new Set <NodeIndex>();
            Dictionary <Loop, IBlockStatement> firstIterPostprocessing = null;

            if (createFirstIterPostBlocks)
            {
                firstIterPostprocessing = GetFirstIterPostprocessing(blocks, graph2, stmts, nodesToMove);
            }
            IVariableDeclaration iteration = Builder.VarDecl("iteration", typeof(int));

            IndexedProperty <NodeIndex, bool> isUniform = graph2.CreateNodeData <bool>(true);

            foreach (StatementBlock block in blocks)
            {
                if (block is Loop)
                {
                    foreach (NodeIndex i in block.indices)
                    {
                        isUniform[i] = false;
                    }
                    IWhileStatement    ws        = Builder.WhileStmt(Builder.LiteralExpr(true));
                    IList <IStatement> whileBody = ws.Body.Statements;

                    if (ContainsIterationStatement(stmts, block.indices))
                    {
                        List <IStatement> nodes = new List <IStatement>();
                        foreach (NodeIndex i in block.indices)
                        {
                            IStatement ist = stmts[i];
                            if (!context.InputAttributes.Has <IterationStatement>(ist))
                            {
                                nodes.Add(ist);
                            }
                        }
                        // build a new dependency graph with the dummy iteration statement removed
                        DependencyGraph   g2  = new DependencyGraph(context, nodes, ignoreMissingNodes: true, ignoreRequirements: true);
                        List <IStatement> sc3 = Schedule(g2, nodes, false);
                        if (sc3.Count == 1 && sc3[0] is IWhileStatement)
                        {
                            ws = (IWhileStatement)sc3[0];
                        }
                        else
                        {
                            // The statements in the outer loop are not strongly connected.
                            // Since we want the next transform to only process strong components,
                            // we mark the outer while loop as DoNotSchedule, leaving only the
                            // inner while loops to be scheduled.
                            // add all statements in sc3 to whileBody, but remove while loops around a single statement.
                            foreach (IStatement ist in sc3)
                            {
                                if (ist is IWhileStatement)
                                {
                                    IWhileStatement iws2 = (IWhileStatement)ist;
                                    if (iws2.Body.Statements.Count == 1)
                                    {
                                        whileBody.AddRange(iws2.Body.Statements);
                                        continue;
                                    }
                                }
                                whileBody.Add(ist);
                            }
                            context.OutputAttributes.Set(ws, new DoNotSchedule());
                        }
                    }
                    else // !ContainsIterationStatement
                    {
                        foreach (NodeIndex i in block.indices)
                        {
                            IStatement st = stmts[i];
                            whileBody.Add(st);
                            DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(st);
                            di.AddClones(clonesOfStatement);
                        }
                        RegisterUnchangedStatements(whileBody);
                    }
                    Loop loop = (Loop)block;
                    if (firstIterPostprocessing != null && firstIterPostprocessing.ContainsKey(loop))
                    {
                        var thenBlock         = firstIterPostprocessing[loop];
                        var iterIsZero        = Builder.BinaryExpr(BinaryOperator.ValueEquality, Builder.VarRefExpr(iteration), Builder.LiteralExpr(0));
                        var firstIterPostStmt = Builder.CondStmt(iterIsZero, thenBlock);
                        context.OutputAttributes.Set(firstIterPostStmt, new FirstIterationPostProcessingBlock());
                        whileBody.Add(firstIterPostStmt);
                    }
                    output.Add(ws);
                }
                else
                {
                    // not cyclic
                    foreach (NodeIndex i in block.indices)
                    {
                        IStatement st = stmts[i];
                        if (!nodesToMove.Contains(i))
                        {
                            output.Add(st);
                            DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(st);
                            di.AddClones(clonesOfStatement);
                        }
                        isUniform[i] = g.IsUniform(i, source => !isUniform[source]);
                        if (isUniform[i] != g.isUniform[i])
                        {
                            Assert.IsTrue(isUniform[i]);
                            g.isUniform[i] = isUniform[i];
                            DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(st);
                            di.IsUniform = isUniform[i];
                        }
                        // mark sources of output statements (for SchedulingTransform)
                        if (g.outputNodes.Contains(i))
                        {
                            foreach (NodeIndex source in graph2.SourcesOf(i))
                            {
                                IStatement sourceSt = stmts[source];
                                if (!context.InputAttributes.Has <OutputSource>(sourceSt))
                                {
                                    context.OutputAttributes.Set(sourceSt, new OutputSource());
                                }
                            }
                        }
                    }
                }
            }
            return(output);
        }