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 ConvertForWithParallelSchedule(IForStatement ifs, IVariableDeclaration loopVar, ParallelScheduleExpression pse) { // Convert this loop into for(block) Parallel.For(thread) for(indexInBlock) IVariableDeclaration loopVarBlock = VariableInformation.GenerateLoopVar(context, loopVar.Name + "_Block"); Sequential sequentialAttr = new Sequential(); context.OutputAttributes.Set(loopVarBlock, sequentialAttr); IVariableDeclaration loopVarInBlock = VariableInformation.GenerateLoopVar(context, loopVar.Name + "_inBlock"); context.OutputAttributes.Set(loopVarInBlock, sequentialAttr); string paramName = VariableInformation.GenerateName(context, loopVar.Name + "_thread"); var threadParam = Builder.Param(paramName, typeof(int)); if (!pse.scheduleExpression.GetExpressionType().Equals(typeof(int[][][]))) { Error("argument to ParallelSchedule attribute is not of type int[][][]"); } IExpression itemsInThread = Builder.ArrayIndex(pse.scheduleExpression, Builder.ParamRef(threadParam)); IExpression itemsInBlock = Builder.ArrayIndex(itemsInThread, Builder.VarRefExpr(loopVarBlock)); IExpression itemCountInBlock = Builder.PropRefExpr(itemsInBlock, typeof(int[]), "Length"); IExpression threadCount = Builder.PropRefExpr(pse.scheduleExpression, typeof(int[][][]), "Length"); IExpression zero = Builder.LiteralExpr(0); IExpression blockCount = Builder.PropRefExpr(Builder.ArrayIndex(pse.scheduleExpression, zero), typeof(int[][]), "Length"); IForStatement loopInBlock = Builder.ForStmt(loopVarInBlock, itemCountInBlock); bool isBackwardLoop = !Recognizer.IsForwardLoop(ifs); 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); //loopInBlock.Body.Statements.AddRange(ifs.Body.Statements); IAnonymousMethodExpression bodyDelegate = Builder.AnonMethodExpr(typeof(Action <int>)); bodyDelegate.Body = Builder.BlockStmt(); bodyDelegate.Body.Statements.Add(loopInBlock); bodyDelegate.Parameters.Add(threadParam); Delegate d = new Func <int, int, Action <int>, ParallelLoopResult>(Parallel.For); IMethodInvokeExpression parallelFor = Builder.StaticMethod(d, zero, threadCount, bodyDelegate); IStatement loopThread = Builder.ExprStatement(parallelFor); IForStatement loopBlock = Builder.ForStmt(loopVarBlock, blockCount); loopBlock.Body.Statements.Add(loopThread); if (isBackwardLoop) { Recognizer.ReverseLoopDirection(loopBlock); } return(loopBlock); }