public void PatchUsersOfCopiedElements( Dictionary<PatternNode, PatternNode> nodeToCopy, Dictionary<PatternEdge, PatternEdge> edgeToCopy, Dictionary<PatternVariable, PatternVariable> variableToCopy) { if(GraphElement != null) { if(GraphElement is PatternNode) { if(nodeToCopy.ContainsKey((PatternNode)GraphElement)) GraphElement = nodeToCopy[(PatternNode)GraphElement]; } else { if(edgeToCopy.ContainsKey((PatternEdge)GraphElement)) GraphElement = edgeToCopy[(PatternEdge)GraphElement]; } } if(Variable != null) { if(variableToCopy.ContainsKey(Variable)) Variable = variableToCopy[Variable]; } if(Attribute != null) { if(Attribute.Owner is PatternNode) { if(nodeToCopy.ContainsKey((PatternNode)Attribute.Owner)) Attribute.Owner = nodeToCopy[(PatternNode)Attribute.Owner]; } else { if(edgeToCopy.ContainsKey((PatternEdge)Attribute.Owner)) Attribute.Owner = edgeToCopy[(PatternEdge)Attribute.Owner]; } } }
public StorageAccessIndex(PatternVariable variable) { Variable = variable; }
// Instantiates a new StorageAccessIndex object as a copy from an original storage access index, used for inlining. public StorageAccessIndex(StorageAccessIndex original) { GraphElement = original.GraphElement; Variable = original.Variable; GlobalVariable = original.GlobalVariable; Attribute = original.Attribute; }
/// <summary> /// Instantiates a new PatternVariable object as a copy from an original variable, used for inlining. /// </summary> /// <param name="original">The original pattern variable to be copy constructed.</param> /// <param name="inlinedSubpatternEmbedding">The embedding which just gets inlined.</param> /// <param name="newHost">The pattern graph the new pattern element will be contained in.</param> /// <param name="nameSuffix">The suffix to be added to the name of the pattern variable (to avoid name collisions).</param> public PatternVariable(PatternVariable original, PatternGraphEmbedding inlinedSubpatternEmbedding, PatternGraph newHost, String nameSuffix) { type = original.type; name = original.name + nameSuffix; unprefixedName = original.unprefixedName + nameSuffix; pointOfDefinition = newHost; defToBeYieldedTo = original.defToBeYieldedTo; initialization = original.initialization; annotations = original.annotations; ParameterIndex = original.ParameterIndex; originalVariable = original; originalSubpatternEmbedding = inlinedSubpatternEmbedding; }
// Instantiates a new StorageAccess object as a copy from an original storage access, used for inlining. public StorageAccess(StorageAccess original) { Variable = original.Variable; GlobalVariable = original.GlobalVariable; Attribute = original.Attribute; }
/// <summary> /// Parallelize the scheduled search plan to the branching factor, /// splitting it at the first loop into a header part and a body part /// </summary> public void ParallelizeHeadBody(LGSPRulePattern rulePattern) { Debug.Assert(rulePattern.patternGraph.schedulesIncludingNegativesAndIndependents.Length == 1); ScheduledSearchPlan ssp = rulePattern.patternGraph.schedulesIncludingNegativesAndIndependents[0]; int indexToSplitAt = 0; for(int i = 0; i < ssp.Operations.Length; ++i) { SearchOperation so = ssp.Operations[i]; if(so.Type == SearchOperationType.Lookup || so.Type == SearchOperationType.Incident || so.Type == SearchOperationType.Incoming || so.Type == SearchOperationType.Outgoing || so.Type == SearchOperationType.PickFromStorage || so.Type == SearchOperationType.PickFromStorageDependent || so.Type == SearchOperationType.PickFromIndex || so.Type == SearchOperationType.PickFromIndexDependent) { indexToSplitAt = i; break; } } rulePattern.patternGraph.parallelizedSchedule = new ScheduledSearchPlan[2]; List<SearchOperation> headOperations = new List<SearchOperation>(); List<SearchOperation> bodyOperations = new List<SearchOperation>(); for(int i = 0; i < rulePattern.Inputs.Length; ++i) { if(rulePattern.Inputs[i] is VarType) // those don't appear in the schedule, they are only extracted into the search program { VarType varType = (VarType)rulePattern.Inputs[i]; String varName = rulePattern.InputNames[i]; PatternVariable dummy = new PatternVariable(varType, varName, varName, i, false, null); headOperations.Add(new SearchOperation(SearchOperationType.WriteParallelPresetVar, dummy, null, 0)); bodyOperations.Add(new SearchOperation(SearchOperationType.ParallelPresetVar, dummy, null, 0)); } } for(int i = 0; i < ssp.Operations.Length; ++i) { SearchOperation so = ssp.Operations[i]; if(i < indexToSplitAt) { SearchOperation clone = (SearchOperation)so.Clone(); clone.Isomorphy.Parallel = true; clone.Isomorphy.LockForAllThreads = true; headOperations.Add(clone); switch(so.Type) { // the target binding looping operations can't appear in the header, so we don't treat them here // the non-target binding operations are completely handled by just adding them, happended already above // the target binding non-looping operations are handled below, // by parallel preset writing in the header and reading in the body // with exception of def, its declaration and initializion is just re-executed in the body // some presets can't appear in an action header, they are thus not taken care of case SearchOperationType.ActionPreset: case SearchOperationType.MapWithStorage: case SearchOperationType.MapWithStorageDependent: case SearchOperationType.Cast: case SearchOperationType.Assign: case SearchOperationType.Identity: case SearchOperationType.ImplicitSource: case SearchOperationType.ImplicitTarget: case SearchOperationType.Implicit: headOperations.Add(new SearchOperation(SearchOperationType.WriteParallelPreset, (SearchPlanNode)so.Element, so.SourceSPNode, 0)); bodyOperations.Add(new SearchOperation(SearchOperationType.ParallelPreset, (SearchPlanNode)so.Element, so.SourceSPNode, 0)); break; case SearchOperationType.AssignVar: headOperations.Add(new SearchOperation(SearchOperationType.WriteParallelPresetVar, (PatternVariable)so.Element, so.SourceSPNode, 0)); bodyOperations.Add(new SearchOperation(SearchOperationType.ParallelPresetVar, (PatternVariable)so.Element, so.SourceSPNode, 0)); break; case SearchOperationType.DefToBeYieldedTo: bodyOperations.Add((SearchOperation)so.Clone()); break; } } else if(i == indexToSplitAt) { SearchOperation cloneHead = (SearchOperation)so.Clone(); headOperations.Add(cloneHead); SearchOperation cloneBody = (SearchOperation)so.Clone(); cloneBody.Isomorphy.Parallel = true; bodyOperations.Add(cloneBody); switch(so.Type) { case SearchOperationType.Lookup: cloneHead.Type = SearchOperationType.SetupParallelLookup; cloneBody.Type = SearchOperationType.ParallelLookup; break; case SearchOperationType.Incident: cloneHead.Type = SearchOperationType.SetupParallelIncident; cloneBody.Type = SearchOperationType.ParallelIncident; break; case SearchOperationType.Incoming: cloneHead.Type = SearchOperationType.SetupParallelIncoming; cloneBody.Type = SearchOperationType.ParallelIncoming; break; case SearchOperationType.Outgoing: cloneHead.Type = SearchOperationType.SetupParallelOutgoing; cloneBody.Type = SearchOperationType.ParallelOutgoing; break; case SearchOperationType.PickFromStorage: cloneHead.Type = SearchOperationType.SetupParallelPickFromStorage; cloneBody.Type = SearchOperationType.ParallelPickFromStorage; break; case SearchOperationType.PickFromStorageDependent: cloneHead.Type = SearchOperationType.SetupParallelPickFromStorageDependent; cloneBody.Type = SearchOperationType.ParallelPickFromStorageDependent; break; case SearchOperationType.PickFromIndex: cloneHead.Type = SearchOperationType.SetupParallelPickFromIndex; cloneBody.Type = SearchOperationType.ParallelPickFromIndex; break; case SearchOperationType.PickFromIndexDependent: cloneHead.Type = SearchOperationType.SetupParallelPickFromIndexDependent; cloneBody.Type = SearchOperationType.ParallelPickFromIndexDependent; break; } } else { SearchOperation clone = (SearchOperation)so.Clone(); clone.Isomorphy.Parallel = true; bodyOperations.Add(clone); if(clone.Element is PatternCondition) SetNeedForParallelizedVersion((clone.Element as PatternCondition).ConditionExpression); } } ScheduledSearchPlan headSsp = new ScheduledSearchPlan( rulePattern.patternGraph, headOperations.ToArray(), headOperations.Count > 0 ? headOperations[0].CostToEnd : 0); rulePattern.patternGraph.parallelizedSchedule[0] = headSsp; ScheduledSearchPlan bodySsp = new ScheduledSearchPlan( rulePattern.patternGraph, bodyOperations.ToArray(), bodyOperations.Count > 0 ? bodyOperations[0].CostToEnd : 0); rulePattern.patternGraph.parallelizedSchedule[1] = bodySsp; ParallelizeNegativeIndependent(bodySsp); ParallelizeAlternativeIterated(rulePattern.patternGraph); ParallelizeYielding(rulePattern.patternGraph); }
/// <summary> /// Inserts inlined variable assignments into the schedule given by the operations list at their earliest possible position /// </summary> public void InsertInlinedVariableAssignmentsIntoSchedule(PatternGraph patternGraph, List<SearchOperation> operations) { // compute the number of inlined parameter variables int numInlinedParameterVariables = 0; foreach(PatternVariable var in patternGraph.variablesPlusInlined) { if(var.AssignmentSource != null && patternGraph.WasInlinedHere(var.originalSubpatternEmbedding)) ++numInlinedParameterVariables; } if(numInlinedParameterVariables == 0) return; // get the inlined parameter variables and the elements needed in order to compute their defining expression Dictionary<String, bool>[] neededElements = new Dictionary<String, bool>[numInlinedParameterVariables]; PatternVariable[] inlinedParameterVariables = new PatternVariable[numInlinedParameterVariables]; int curInlParamVar = 0; foreach(PatternVariable var in patternGraph.variablesPlusInlined) { if(var.AssignmentSource == null) continue; if(!patternGraph.WasInlinedHere(var.originalSubpatternEmbedding)) continue; neededElements[curInlParamVar] = new Dictionary<string, bool>(); foreach(String neededNode in var.AssignmentDependencies.neededNodes) neededElements[curInlParamVar][neededNode] = true; foreach(String neededEdge in var.AssignmentDependencies.neededEdges) neededElements[curInlParamVar][neededEdge] = true; inlinedParameterVariables[curInlParamVar] = var; ++curInlParamVar; } // iterate over all inlined parameter variables for(int i = 0; i < inlinedParameterVariables.Length; ++i) { int j; float costToEnd = 0; // find leftmost place in scheduled search plan for current assignment // by search from end of schedule forward until the first element the expression assigned is dependent on is found for(j = operations.Count - 1; j >= 0; --j) { SearchOperation op = operations[j]; if(op.Type == SearchOperationType.Condition || op.Type == SearchOperationType.Assign || op.Type == SearchOperationType.AssignVar || op.Type == SearchOperationType.NegativePattern || op.Type == SearchOperationType.IndependentPattern || op.Type == SearchOperationType.DefToBeYieldedTo) { continue; } if(neededElements[i].ContainsKey(((SearchPlanNode)op.Element).PatternElement.Name)) { costToEnd = op.CostToEnd; break; } } SearchOperation so = new SearchOperation(SearchOperationType.AssignVar, inlinedParameterVariables[i], null, costToEnd); so.Expression = inlinedParameterVariables[i].AssignmentSource; operations.Insert(j + 1, so); } }
/// <summary> /// Search program operations implementing the /// ParallelPresetVar search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildParallelPresetVar( SearchProgramOperation insertionPoint, int currentOperationIndex, PatternVariable target) { // get candidate from parallelization preset GetCandidateByDrawing fromInputs = new GetCandidateByDrawing( GetCandidateByDrawingType.FromParallelizationTaskVar, target.Name, TypesHelper.TypeName(target.Type)); insertionPoint = insertionPoint.Append(fromInputs); //--------------------------------------------------------------------------- // build next operation insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram( currentOperationIndex + 1, insertionPoint); //--------------------------------------------------------------------------- return insertionPoint; }
/// <summary> /// Search program operations implementing the /// WriteParallelPresetVar search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildWriteParallelPresetVar( SearchProgramOperation insertionPoint, int currentOperationIndex, PatternVariable target) { // write parallel preset var WriteParallelPresetVar writePresetVar = new WriteParallelPresetVar( target.Name, TypesHelper.TypeName(target.Type)); insertionPoint = insertionPoint.Append(writePresetVar); //--------------------------------------------------------------------------- // build next operation insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram( currentOperationIndex + 1, insertionPoint); //--------------------------------------------------------------------------- return insertionPoint; }
/// <summary> /// Search program operations implementing the /// AssignVar search plan operation /// are created and inserted into search program /// </summary> private SearchProgramOperation buildAssignVar( SearchProgramOperation insertionPoint, int currentOperationIndex, PatternVariable variable, Expression expression) { // generate c#-code-string out of condition expression ast SourceBuilder assignmentExpression = new SourceBuilder(); expression.Emit(assignmentExpression); // get candidate from other element (the cast is simply the following type check) AssignVariableFromExpression assignVar = new AssignVariableFromExpression( variable.Name, TypesHelper.TypeName(variable.type), assignmentExpression.ToString()); insertionPoint = insertionPoint.Append(assignVar); //--------------------------------------------------------------------------- // build next operation insertionPoint = BuildScheduledSearchPlanOperationIntoSearchProgram( currentOperationIndex + 1, insertionPoint); //--------------------------------------------------------------------------- return insertionPoint; }