-
Notifications
You must be signed in to change notification settings - Fork 635
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
DYN-1722 #9578
DYN-1722 #9578
Conversation
@reddyashish have you had a chance to try running this change over a set of graphs before and after using the perf console app? |
Not yet, discussed this with Aparajit and we will be doing it next. We would be needing a set of large graphs that would be testing cases involving function match resolution. Any idea on if we got any? |
I am sure if we can be specific about what graph types we want @JacobSmall and @Amoursol can provide a bunch. |
If I don’t have one ready I can likely build one (or ten) up pretty quickly. Looking for a lot of nodes or a lot of objects? |
@reddyashish please enumerate and explain the case(s) that are yet to be fixed. You mentioned that the second example in DYN-1496 isn't fixed but you can generalize it a bit more; for example: |
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.
Ashish, I don’t fully understand the code change especially the IsCompatible function. I saw the 2 test failures you mentioned on self serve and I didn’t see why the above change was required to address them?
private Boolean IsCompatibleReplicationOption(List<ReplicationInstruction> oldOption, List<ReplicationInstruction> newOption) | ||
{ | ||
if (oldOption.Count > 0 && newOption.Count > 0 && oldOption.Count < newOption.Count) | ||
{ |
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.
I’m not sure I understand this change. Why are you checking equality only for the first option?
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.
For those 2 cases where it was failing, as we are checking for all the replication options(to find a match), the first match is found for "cartesian:indices=0" option. Then it finds a match for "zipped:indices=0,1" and it applies zipped replication option(as this is the final option that is tested). Previously, the first option that found a match was applied directly. After this change, it would not accept the zipped replication as the cartesian option has already found the match.
Another case is, we want to accept this new replication option, if it is of the higher rank than the previous option (old option: "cartesian:indices=0" and new option: "cartesian:indices=0, cartesian:indices=0". Similar option but checks for one extra depth level). Since all options are unique, I was checking the first element and the count for the new option to be higher than the first. Also can use, newOption.Count = oldOption.Count +1.
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.
I'm definitely having a hard time understanding this one, is it possible @reddyashish you could draw a diagram or do a longer writeup of the problem here and the approach taken to fix it - I know it's kind of a tall order.
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.
so - I'm trying to think of cases where this will fail -
I think naming this method or adding a summary might help - but my interpretation is that this method is used to find List<ReplicationInstruction>
where the first instruction matches the previous one but is of a greater depth?
What I cannot figure out or explain yet is what case this is used to avoid or to guarantee we hit? Can you try to sum it up in the summary of the method or in the git here.
} | ||
} | ||
if (matchFound) | ||
return; |
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.
@reddyashish so - what about case 5 - why do we exit the other cases late, and exit case 5 as soon as we find a match?
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.
I did not understand this case and it adds an empty replication option to the previous list and finds the match. I was not able to find any examples related to this case.
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.
I will try to find when it's called.
@saintentropy any ideas?
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.
@mjkkirschner @reddyashish In general this whole function is still black magic to me. I have been able to look at indivual examples and how they flow through but it is hard to make judgment on individual PR's without holistic picture. I think we need to document examples of different data, data structures, replication settings, and functions and what the result replication instruction and function endpoint list. Not sure if we need to do that on this PR but it is hard to validate the code changes otherwise
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.
For a start - I've filed a followup task to cover each of the missing cases with explicit tests.
I think these cases really need examples. I know they are not new, but I think if you have some idea about which types of function calls apply to which cases those examples inline would be a good addition to the comments. |
return; | ||
if (replicationInstructions == null || IsCompatibleReplicationOption(replicationInstructions, replicationOption)) | ||
{ | ||
//Otherwise we have a cluster of FEPs that can be used to dispatch the array |
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.
I find this comment confusing - what is the otherwise
referring to - theres no comment before this and we are inside an if statement... not an else statement -
@@ -44,5 +45,22 @@ public override string ToString() | |||
} | |||
|
|||
} | |||
|
|||
public Boolean Equals(ReplicationInstruction oldOption) { |
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.
this does not seem to actually perform a full equality check... it only returns true for zip replication - you should override Equals like this
https://docs.microsoft.com/en-us/dotnet/api/system.object.equals?view=netframework-4.7.2
use the override keyword
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's a struct - so @reddyashish you may want to read this:
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type
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.
@mjkkirschner Do you want me change anything in this Equals method after our discussion on friday or is this ok?
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.
hmm, well I guess I am a bit confused why you do not just compare the properties directly? ie Why all the use of Except?
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.
Added the comments to code, on why we can use Except to compare the elements in both the lists.
@reddyashish thanks for updating comments and tests - is the only thing left that we discussed the performance testing of a pathologically bad case? (super nested?) or many many parameter function? |
if (this.Zipped == oldOption.Zipped) | ||
{ | ||
if (this.ZipIndecies == null && oldOption.ZipIndecies == null) | ||
return true; |
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.
why is this true even if the zip algorithm is different?
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.
Added the zipAlgorithm check.
if (this.ZipIndecies == null && oldOption.ZipIndecies == null) | ||
return true; | ||
|
||
if (this.ZipIndecies != null && oldOption.ZipIndecies != null) |
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.
I'm not getting something here - can you add a comment - but like I said above, I'm confused why we're not using sequence equals or something like that?
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.
@reddyashish explained this is an optimization.
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.
Fastest way to compare elements of both the lists:
https://stackoverflow.com/questions/12795882/quickest-way-to-compare-two-list
I have added comments to the code.
@reddyashish - Is this ready to merge? |
The self-serve looks good. The performance benchmark tests for the graphs(created by Scott) are still running, so once that is done we can merge it. |
Performance benchmark results for graphs in here:https://github.com/DynamoDS/Dynamo/tree/master/tools/Performance/DynamoPerformanceTests/graphs Both the times, the run time was higher than what Scott has reported in his PR. I followed up with Scott and he will be running them again on his machine to see if he can see any difference. |
@scottmitchell - we really need to figure out how to get the full name in the performance results output 😉... @reddyashish what do you make of those results? |
The Mean, Error, StdDev values are not that different but the run time is. That is confusing to me. |
if you ran the tests in parallel it makes sense they will have longer run time - it also appears that it ran them both different numbers of times in each comparison - I would look only at the benchmark times relative to each other (before and after), not the total runtime. |
* DYN-1722 * Variable change name * Update the callsite.cs * Modifying the equals function. * adding comments * Test comments * Changing variable name * Adding zipAlgorithm check and comments. * More Comments. (cherry picked from commit 62e1b56)
* Cherry-picking #9388 into 2.0.3 * Cherry-picking #9559 into 2.0.3 * Cherry-picking #9578 into 2.0.3 * cherry-picking #9632 into 2.0.3 * cherry-picking #9408 into 2.0.3 * cherry-picking #9441 into 2.0.3 * Adding gradient.png for the Test_PerforationsByImage test. This was missed while cherrypicking #9441 * Removing DSCoreDataTests.cs as this was the test fixture was introduced in a different commit and is not needed here.
Purpose
This PR is to address a regression issue from 2.0. (https://jira.autodesk.com/browse/DYN-1722)
This also fixes most of the non-regressions from https://jira.autodesk.com/browse/DYN-1496. The only case that is failing would be the second case in the description of the above JIRA.
Explanation:
Instead of the just returning the first replication option that matches the target function, we check for all the replications that match the target function and then choose the replication option with largest rank. In the case where both cartesian and zipped replication options are possible, we check for the first option that matches the target function and modify the replication option(in next iterations) only if
a similar replication option, with a higher rank, is matched with the target function.
Performance test results on around 11 graphs:
Before the fix:
After the fix:
Declarations
Check these if you believe they are true
*.resx
filesReviewers
@aparajit-pratap @mjkkirschner @QilongTang