Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smarter default number of workers in C runtime #1139

Merged
merged 10 commits into from
May 10, 2022
2 changes: 1 addition & 1 deletion org.lflang/src/lib/c/reactor-c
52 changes: 21 additions & 31 deletions org.lflang/src/org/lflang/generator/ReactionInstanceGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,20 @@ public void rebuild() {
public Integer[] getNumReactionsPerLevel() {
return numReactionsPerLevel.toArray(new Integer[0]);
}


/**
* Return the max breadth of the reaction dependency graph
*/
public int getBreadth() {
var maxBreadth = 0;
for (Integer breadth: numReactionsPerLevel ) {
if (breadth > maxBreadth) {
maxBreadth = breadth;
}
}
return maxBreadth;
}

///////////////////////////////////////////////////////////
//// Protected methods

Expand Down Expand Up @@ -232,7 +245,7 @@ protected void addNodesAndEdges(ReactorInstance reactor) {
*/
private List<Integer> numReactionsPerLevel = new ArrayList<>(
List.of(Integer.valueOf(0)));

///////////////////////////////////////////////////////////
//// Private methods

Expand All @@ -251,7 +264,7 @@ private void assignLevels() {

// All root nodes start with level 0.
for (Runtime origin : start) {
assignLevel(origin, 0);
origin.level = 0;
}

// No need to do any of this if there are no root nodes;
Expand All @@ -260,17 +273,14 @@ private void assignLevels() {
Runtime origin = start.remove(0);
Set<Runtime> toRemove = new LinkedHashSet<Runtime>();
Set<Runtime> downstreamAdjacentNodes = getDownstreamAdjacentNodes(origin);
// All downstream adjacent nodes start with a level 0. Adjust the
// <code>numReactionsPerLevel<code> field accordingly (to be
// updated in the for loop below).
adjustNumReactionsPerLevel(0, downstreamAdjacentNodes.size());

// Visit effect nodes.
for (Runtime effect : downstreamAdjacentNodes) {
// Stage edge between origin and effect for removal.
toRemove.add(effect);

// Update level of downstream node.
updateLevel(effect, origin.level+1);
effect.level = origin.level + 1;
}
// Remove visited edges.
for (Runtime effect : toRemove) {
Expand All @@ -284,32 +294,12 @@ private void assignLevels() {

// Remove visited origin.
removeNode(origin);

// Update numReactionsPerLevel info
adjustNumReactionsPerLevel(origin.level, 1);
}
}

/**
* Assign a level to a reaction runtime instance.
*
* @param runtime The reaction runtime instance.
* @param level The level to assign.
*/
private void assignLevel(Runtime runtime, Integer level) {
runtime.level = level;
adjustNumReactionsPerLevel(level, 1);
}

/**
* Update the level of the reaction <code>runtime<code> instance
* to <code>level<code> if <code>level<code> is larger than the
* level already assigned to <code>runtime<code>.
*/
private void updateLevel(Runtime runtime, Integer level) {
if (runtime.level < level) {
adjustNumReactionsPerLevel(runtime.level, -1);
runtime.level = level;
adjustNumReactionsPerLevel(level, 1);
}
}

/**
* Adjust {@link #numReactionsPerLevel} at index <code>level<code> by
Expand Down
34 changes: 24 additions & 10 deletions org.lflang/src/org/lflang/generator/c/CGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) {
LFGeneratorContext generatingContext = new SubContext(
context, IntegratedBuilder.VALIDATED_PERCENT_PROGRESS, IntegratedBuilder.GENERATED_PERCENT_PROGRESS
);

for (FederateInstance federate : federates) {
currentFederate = federate;
federateCount++;
Expand Down Expand Up @@ -2744,22 +2745,35 @@ private void createMainReactorInstance() {
// it is the same for all federates.
this.main = new ReactorInstance(toDefinition(mainDef.getReactorClass()), errorReporter,
this.unorderedReactions);
if (this.main.assignLevels().nodeCount() > 0) {
var reactionInstanceGraph = this.main.assignLevels();
if (reactionInstanceGraph.nodeCount() > 0) {
errorReporter.reportError("Main reactor has causality cycles. Skipping code generation.");
return;
}
// Force reconstruction of dependence information.
if (isFederated) {
// Avoid compile errors by removing disconnected network ports.
// This must be done after assigning levels.
removeRemoteFederateConnectionPorts(main);
// There will be AST transformations that invalidate some info
// cached in ReactorInstance.
this.main.clearCaches(false);
// Inform the run-time of the breadth/parallelism of the reaction graph
var breadth = reactionInstanceGraph.getBreadth();
if(breadth == 0) {
lhstrh marked this conversation as resolved.
Show resolved Hide resolved
errorReporter.reportWarning("Reaction graph breadth is computed to be 0. Indicates an error");
} else {
targetConfig.compileDefinitions.put(
"LF_REACTION_GRAPH_BREADTH",
String.valueOf(reactionInstanceGraph.getBreadth())
);
}
}
}

// Force reconstruction of dependence information.
if (isFederated) {
// Avoid compile errors by removing disconnected network ports.
// This must be done after assigning levels.
removeRemoteFederateConnectionPorts(main);
// There will be AST transformations that invalidate some info
// cached in ReactorInstance.
this.main.clearCaches(false);
}
}
}


/**
* Generate an array of self structs for the reactor
Expand Down