-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Compile recursive iterators to sub-linear time complexity code. Now it is compiled to quadratic time complexity code. #25052
Comments
It's not clear to me how exactly would the translation work. For example, consider this code: IEnumerable<T> DumpAndIterateFromBack<T>(LinkedListNode<T> node)
{
if (node == null)
yield break;
foreach (var x in DumpAndIterateFromBack(node.Previous))
yield return x;
Console.WriteLine(node.Value);
yield return node.Value;
} How would you translate it to use your Hyperloop? |
@svick Now my |
@svick I added support of code with side effects in So next code static IEnumerable<int> DumpAndIterateFromBack(int e)
{
if (e <= 0)
yield break;
foreach (var x in DumpAndIterateFromBack(e - 1))
yield return x;
Console.WriteLine(e);
yield return e;
} can be translated to next code: static IEnumerable<int> DumpAndIterateFromBack_Hl(int e)
{
var hl = new Hyperloop<int>();
hl.Add(DumpAndIterateFromBack_HlImp(hl, e));
return hl;
}
static IEnumerable<int> DumpAndIterateFromBack_HlImp(IHyperloop<int> hl, int e)
{
if (e <= 0)
yield break;
hl.Add(DumpAndIterateFromBack_HlImp(hl, e - 1));
yield return default(int); // will be skiped to support code with side effects
Console.WriteLine(e);
yield return e;
} So only the loop part: foreach (var x in DumpAndIterateFromBack(e - 1))
yield return x; Translated to hl.Add(DumpAndIterateFromBack_HlImp(hl, e - 1));
yield return default(int); // will be skiped to support code with side effects all other code is the same. |
@KrisVandermotten I think here https://github.com/AlexRadch/YieldForEachDN I implemented the same ideas as in https://www.researchgate.net/publication/228625370_Iterators_revisited_Proof_rules_and_implementation/. |
@Wolfram-Schulte what are you think about my recursive iterators transformation for effective implementation? |
We would consider a community contribution that addresses this feature request provided the implementation is sufficiently simple and well isolated in the compilers. |
I would like to try and tackle this. My current plan would be to use something like What is the best way to recognize that a sequence has been generated according to these rules (or, which would be the same to me, supports both the "single result" and the "sequence result")? |
We would need a solution that came with no perf impact on any existing code. |
Yup, the idea is to only change the codegen if the method contains a |
Hello, I'd like to have a crack at this. My current understanding: When writing an iterator function that iterates over another iterator function and If I understand the research paper's intuition what it does is not propagate values 'upward' but instead have the outer-most iterator point directly to the nested iterator which is 'currently' active, however deep it may be. Thus avoiding the costly propagation. There is a suggestion to enable new Is my understanding correct and would the suggested approach be desired? |
@ArcadeMode the critical thing is that any existing code that does a standard foreach over any existing IEnumerables (or anything foreach operates on) not have any negative impact whatsoever. |
I found the discussion in the csharplang repo and noticed that the suggested approaches are unsuitable. Its a marvelously complex issue for sure! The related discussion about supporting (I am still getting familar with this part of roslyn so if im about to spew nonsense dont hesitate to tell me). What I am thinking is to use Furthermore this would not touch I would love your feedback on this. |
Could you give an example of:
Thanks! |
Compile recursive iterators to sub-linear time complexity code. Now it is compiled to quadratic time complexity code.
Any version:
Recursive iterations code is compiled to quadratic time complexity code.
Steps to Reproduce:
Expected Behavior:
Sub-linear time complexity.
Actual Behavior:
Quadratic time complexity.
Such code is compiled to loop in loop in loop and so on. All that they do is to return values from recursive loops but have quadratic time complexity.
Work around
Use separated loop and replace recursive calls by linear loops. Here https://github.com/AlexRadch/YieldForEachDN I created such loop (I called it
Hyperloop
). It supportIHyperloop
interface with two methods:Then any recursive calls can be replaced by adding loops to
IHyperloop
.For example next iterator:
Can be converted to iterator without loops in loops in loops and so on:
Here
RangeRecursive1_Hl
is proxy that createHyperloop
and addRangeRecursive1_HlImp
iterator toHyperloop
. TheRangeRecursive1_HlImp
code is similar to original code except that loop code replaced by adding loops toIHyperloop
.Code converted to
Suggestion:
The small code transformation can reduce quadratic time complexity to sub-linear time complexity in recursive iterators.
So I suggest detect recursive iterators (it is easy) and use such small code transformation in
roslyn
compiler to reduce time complexity.The text was updated successfully, but these errors were encountered: