-
Notifications
You must be signed in to change notification settings - Fork 63
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
Conversation
2. Use it + RunTime.numberOfProcessors to pick a smart number of workers
Hi @erlingrj Thanks for submitting this PR. The threaded C runtime determines the number of workers at runtime. I personally prefer the existing approach because we use the number of cores of the machine that executes the program, not the number of cores of the machine that code generates the program. In keeping with the current scheme of things, the calculated breadth would simply have to be conveyed to the C runtime. But, if you think we should determine the number of cores statically at code generation time, we should remove the duplicate logic in the C runtime. |
Another alternative would be to pass the breadth as a flag through CMake. Then the runtimes could do the comparison of available cores and breadth of reaction graph themselves. In my opinion, it would be better to not do the reaction-graph analysis during run-time. But I think you have a more qualified opinion than me |
That sounds like a great strategy. I think your code can slightly be adjusted to accommodate this design. In createMainReactorInstance, you could add the following logic: if (this.mainDef != null) {
if (this.main == null) {
// Recursively build instances. This is done once because
// it is the same for all federates.
this.main = new ReactorInstance(toDefinition(mainDef.getReactorClass()), errorReporter,
this.unorderedReactions);
+ var reactionInstanceGraph = this.main.assignLevels();
- if (this.main.assignLevels().nodeCount() > 0) {
+ if (reactionInstanceGraph.nodeCount() > 0) {
errorReporter.reportError("Main reactor has causality cycles. Skipping code generation.");
return;
}
+ if (targetConfig.workers == 0) {
+ targetConfig.compileDefinitions.put(
+ "LF_REACTION_GRAPH_BREADTH",
+ reactionInstanceGraph.getMaxBreadth()
+ )
+ }
// 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);
}
}
} The C runtime can then take |
You say:
But if the reaction graph breadth is getting calculated correctly, the breadth should be 1 in this case. |
Add CMake compile flag LF_REACTION_GRAPH_BREADTH in case of 0 workers
I added your suggestion @Soroosh129. There was some confusion that maybe you can help me with. What is it that ReactionInstanceGraph is referring to with numReactionsAtLevel? I am not really sure what it is counting, but it is not what I expected. To find the breadth of the graph I added my own logic into the assignLevels functions. And count the breadth with "numIndependentReactionsPerLevel". An example of this is the following graph: Where numReactionsPerLevel= [3,2,2,1] |
In this example, I'm pretty sure what we want is numIndependentReactionsPerLevel=[1,2,2,1]. |
[3, 2, 2, 1] sounds incorrect to me as well. I think numIndependentReactionsPerLevel is actually what we want. Would it be possible to merge these two logic (or get rid of the old one)? |
I will look into that |
I merged them now. It works on a few examples here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! Thank you for taking care of this issue.
We should perhaps do a performance comparison before and after this change but I don’t think that should block merging this in.
errorReporter.reportError("Main reactor has causality cycles. Skipping code generation."); | ||
return; | ||
} | ||
// In case of 0 workers. Inform the runtime of the reaction graph breadth | ||
// FIXME: Should this flag be added regardless of number of workers specified? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! Yes, I think there is no need to check the number of workers here.
String.valueOf(reactionInstanceGraph.getBreadth()) | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the indentation is incorrect.
By the way, I think it might be better if the necessary changes to reactor-c were also a part of this PR for the sake of completeness. |
How do you structure PRs that include multiple git-repos? I have made a PR in reactor-c with the same name here |
You can update the hash that is pointing to a particular commit in reactor-c via a |
This looks good, but I see some conflicts arose in the meantime. If you can fix these, we can quickly go ahead and merge this in. Thanks! |
# Conflicts: # org.lflang/src/org/lflang/generator/c/CGenerator.java
I merged the the PR locally. |
I thought I'd address some minor issues as a way of familiarizing myself with the codebase.
This is adressing issue with a smarter default number of workers #1096. Currently only implemented for C. In case the user does not specify the number of worker threads, we use the minimum of the number of cores and the breadth of the Reaction graph. With this proposal the C (and in the future the C++ and Rust) runtime will always be configured with a specific number of workers.
Questions:
When questions are resolved I can port to the other target language generators