예제 #1
0
        private void SearchRangeAttributes(Range range)
        {
            IVariableDeclaration ivd = range.GetIndexDeclaration();

            foreach (ICompilerAttribute attr in range.GetAttributes <ICompilerAttribute>())
            {
                if (attr is ParallelSchedule ps)
                {
                    toSearch.Push(ps.scheduleExpression);
                    var attr2 = new ParallelScheduleExpression(ps.scheduleExpression.GetExpression());
                    Attributes.Set(ivd, attr2);
                }
                else if (attr is DistributedSchedule ds)
                {
                    toSearch.Push(ds.commExpression);
                    if (ds.scheduleExpression != null)
                    {
                        toSearch.Push(ds.scheduleExpression);
                    }
                    if (ds.schedulePerThreadExpression != null)
                    {
                        toSearch.Push(ds.schedulePerThreadExpression);
                    }
                    var attr2 = new DistributedScheduleExpression(ds.commExpression.GetExpression(), ds.scheduleExpression?.GetExpression(), ds.schedulePerThreadExpression?.GetExpression());
                    Attributes.Set(ivd, attr2);
                }
                else
                {
                    Attributes.Set(ivd, attr);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Search all variables referred to by a Range.
        /// </summary>
        /// <param name="range"></param>
        private void SearchRange(Range range)
        {
            if (searched.Contains(range))
            {
                return;
            }
            string name = ((IModelExpression)range).Name;

            foreach (IModelExpression expr in searched)
            {
                if (name.Equals(expr.Name))
                {
                    throw new InferCompilerException("Model contains multiple items with the name '" + name + "'.  Names must be unique.");
                }
            }
            searched.Add(range);
            toSearch.Push(range.Size);
            IVariableDeclaration ivd = range.GetIndexDeclaration();

            foreach (ICompilerAttribute attr in range.GetAttributes <ICompilerAttribute>())
            {
                if (attr is ParallelSchedule)
                {
                    var ps = (ParallelSchedule)attr;
                    toSearch.Push(ps.scheduleExpression);
                    var attr2 = new ParallelScheduleExpression(ps.scheduleExpression.GetExpression());
                    Attributes.Set(ivd, attr2);
                }
                else if (attr is DistributedSchedule)
                {
                    var ds = (DistributedSchedule)attr;
                    toSearch.Push(ds.commExpression);
                    if (ds.scheduleExpression != null)
                    {
                        toSearch.Push(ds.scheduleExpression);
                    }
                    if (ds.schedulePerThreadExpression != null)
                    {
                        toSearch.Push(ds.schedulePerThreadExpression);
                    }
                    var attr2 = new DistributedScheduleExpression(ds.commExpression.GetExpression(), ds.scheduleExpression?.GetExpression(), ds.schedulePerThreadExpression?.GetExpression());
                    Attributes.Set(ivd, attr2);
                }
                else
                {
                    Attributes.Set(ivd, attr);
                }
            }
        }
        /// <summary>
        /// Converts 'for' loops with ParallelSchedule attributes into parallel for loops.
        /// </summary>
        /// <param name="ifs">The for loop to convert</param>
        /// <returns>The converted statement</returns>
        protected override IStatement ConvertFor(IForStatement ifs)
        {
            if (context.InputAttributes.Has <ConvergenceLoop>(ifs) || (ifs is IBrokenForStatement))
            {
                return(base.ConvertFor(ifs));
            }
            IVariableDeclaration       loopVar = Recognizer.LoopVariable(ifs);
            ParallelScheduleExpression pse     = context.InputAttributes.Get <ParallelScheduleExpression>(loopVar);

            if (pse != null)
            {
                return(ConvertForWithParallelSchedule(ifs, loopVar, pse));
            }
            DistributedScheduleExpression dse = context.InputAttributes.Get <DistributedScheduleExpression>(loopVar);

            if (dse != null)
            {
                return(ConvertForWithDistributedSchedule(ifs, loopVar, dse));
            }
            return(base.ConvertFor(ifs));
        }
        private IForStatement ConvertForWithDistributedSchedule(IForStatement ifs, IVariableDeclaration loopVar, DistributedScheduleExpression dse)
        {
            if (dse.scheduleExpression == null && dse.schedulePerThreadExpression == null)
            {
                return((IForStatement)base.ConvertFor(ifs));
            }
            Sequential attr = context.InputAttributes.Get <Sequential>(loopVar);

            if (attr == null || !attr.BackwardPass)
            {
                Error($"Range '{loopVar.Name}' has a DistributedSchedule attribute but does not have a Sequential attribute with BackwardPass = true");
            }
            // Convert this loop into for(stage) for(indexInBlock) { ... }
            IVariableDeclaration loopVarBlock   = VariableInformation.GenerateLoopVar(context, loopVar.Name + "_Block");
            Sequential           sequentialAttr = new Sequential();

            context.OutputAttributes.Set(loopVarBlock, sequentialAttr);
            bool isBackwardLoop = !Recognizer.IsForwardLoop(ifs);

            this.distributedCommunicationExpressions.Clear();
            IForStatement loopInBlock;
            IExpression   zero = Builder.LiteralExpr(0);
            IExpression   distributedStageCount;

            if (dse.schedulePerThreadExpression != null)
            {
                var scheduleForBlock = Builder.ArrayIndex(dse.schedulePerThreadExpression, Builder.VarRefExpr(loopVarBlock));
                distributedStageCount = Builder.PropRefExpr(dse.schedulePerThreadExpression, typeof(int[][][][]), "Length");
                loopInBlock           = ConvertForWithParallelSchedule(ifs, loopVar, new ParallelScheduleExpression(scheduleForBlock));
            }
            else
            {
                IVariableDeclaration loopVarInBlock = VariableInformation.GenerateLoopVar(context, loopVar.Name + "_inBlock");
                context.OutputAttributes.Set(loopVarInBlock, sequentialAttr);
                if (!dse.scheduleExpression.GetExpressionType().Equals(typeof(int[][])))
                {
                    Error("argument to DistributedSchedule attribute is not of type int[][]");
                }
                IExpression itemsInBlock     = Builder.ArrayIndex(dse.scheduleExpression, Builder.VarRefExpr(loopVarBlock));
                IExpression itemCountInBlock = Builder.PropRefExpr(itemsInBlock, typeof(int[]), "Length");
                distributedStageCount = Builder.PropRefExpr(dse.scheduleExpression, typeof(int[][]), "Length");
                loopInBlock           = Builder.ForStmt(loopVarInBlock, itemCountInBlock);
                if (isBackwardLoop)
                {
                    Recognizer.ReverseLoopDirection(loopInBlock);
                }
                var assignLoopVar = Builder.AssignStmt(Builder.VarDeclExpr(loopVar), Builder.ArrayIndex(itemsInBlock, Builder.VarRefExpr(loopVarInBlock)));
                loopInBlock.Body.Statements.Add(assignLoopVar);
                ConvertStatements(loopInBlock.Body.Statements, ifs.Body.Statements);
            }
            IForStatement loopBlock = Builder.ForStmt(loopVarBlock, distributedStageCount);
            IExpression   commExpr  = dse.commExpression;

            if (isBackwardLoop)
            {
                loopBlock.Body.Statements.Add(loopInBlock);
                foreach (var tuple in this.distributedCommunicationExpressions)
                {
                    var         arrayExpr         = tuple.Item1;
                    var         dce               = tuple.Item2;
                    IExpression sendExpr          = Builder.ArrayIndex(dce.arrayIndicesToSendExpression, Builder.VarRefExpr(loopVarBlock));
                    IExpression receiveExpr       = Builder.ArrayIndex(dce.arrayIndicesToReceiveExpression, Builder.VarRefExpr(loopVarBlock));
                    var         sendReceiveMethod = Builder.StaticGenericMethod(new Action <ICommunicator, IList <PlaceHolder>, int[][], int[][]>(Communicator.AlltoallSubarrays),
                                                                                new Type[] { Utilities.Util.GetElementType(arrayExpr.GetExpressionType()) },
                                                                                commExpr, arrayExpr,
                                                                                receiveExpr,
                                                                                sendExpr);
                    loopBlock.Body.Statements.Add(Builder.ExprStatement(sendReceiveMethod));
                }
                Recognizer.ReverseLoopDirection(loopBlock);
            }
            else
            {
                foreach (var tuple in this.distributedCommunicationExpressions)
                {
                    var         arrayExpr         = tuple.Item1;
                    var         dce               = tuple.Item2;
                    IExpression sendExpr          = Builder.ArrayIndex(dce.arrayIndicesToSendExpression, Builder.VarRefExpr(loopVarBlock));
                    IExpression receiveExpr       = Builder.ArrayIndex(dce.arrayIndicesToReceiveExpression, Builder.VarRefExpr(loopVarBlock));
                    var         sendReceiveMethod = Builder.StaticGenericMethod(new Action <ICommunicator, IList <PlaceHolder>, int[][], int[][]>(Communicator.AlltoallSubarrays),
                                                                                new Type[] { Utilities.Util.GetElementType(arrayExpr.GetExpressionType()) },
                                                                                commExpr, arrayExpr,
                                                                                sendExpr,
                                                                                receiveExpr);
                    loopBlock.Body.Statements.Add(Builder.ExprStatement(sendReceiveMethod));
                }
                loopBlock.Body.Statements.Add(loopInBlock);
            }
            return(loopBlock);
        }