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); } } }
/// <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); }