Date: Fri, 10 Dec 2021 11:05:42 +0800
Hi Phil,
Inline in C++ has different meaning in compiler. But I guess you already knew this : )
I think that your idea for "inline coroutine" would be the proposal.
A bottleneck for this idea I could see is that this is hard to implement. For example,
the C++ coroutine would be splitted in clang. And clang/LLVM banned inlining a coroutine
before it gets splitted due to complicated semantic problems.
I understand that this is a language list so that "it is hard to implement" might not be
a good argument. And another problem that any idea that want to mark
special attribute for coroutine might met is that it couldn't handle indirect call and definitions
in another TU.
For example, if I mark a virtual coroutine as "inline coroutine", then the compiler is unable to
know the callee during compilation time. This is similar for functions whose definition are in
another TU. This is beyond "the compiler is hard to implement". I think it is constrained by the
fundamental design.
There would be other problems. For example, what would happen if a "inline coroutine" get called
in normal function. What would happen if a "inline coroutine" get called in a coroutine with different
coroutine promise_type? I believe it would be very complicated.
Finally, I don't think the call overhead might be significant. My experience for the performance of coroutine
is that the main overhead comes from dynamic allocation. Another one is exception. If you are
not in an environment that could disable exception, it might be helpful to mark many functions/coroutines as noexcept.
And the performanace advantage of coroutine occurs when the concurrency is very high.
It would absolutely good to optimize the performance of coroutine in single thread. But the performance of coroutine
would be worse than normal function after all since it generates more code.
Thanks,
Chuanqi
------------------------------------------------------------------
From:Phil Endecott via Std-Proposals <std-proposals_at_[hidden]>
Send Time:2021年12月10日(星期五) 00:28
To:std-proposals <std-proposals_at_[hidden]>
Cc:Phil Endecott <std_proposals_list_at_[hidden]>
Subject:[std-proposals] inline coroutine generators
Dear Experts,
I have recently been experimenting with generators for the
first time.
One issue that bothers me is inlining. For example:
generator<char> g1()
{
for (.....) {
co_yield x;
if (......) g2(a);
if (......) g2(b);
g2(a+b);
}
}
static ??? g2(int)
{
for (....) {
co_yield ....;
}
}
What I'm trying to convey with that pseudocode is that I've
decomposed a largish block of code by factoring out some common
bits into another routine. If these were functions this would be
unproblematic; the compiler would likely inline and if it didn't
the function call overhead would be modest. But because it's a
coroutine, things are more complicated. Given the complexity of
the recursive generator implementation, I don't think that there
is any real prospect of g2 being properly inlined into g1, is
there?
What bothers me is that if I wrote g2 as a macro, it would of
course be perfectly inlined.
We don't want to find that we have a choice between (a) over-long
functions with duplicated code, (b) macros, (c) nicely organised
code that is slow.
This makes me wonder if some special meaning for "inline" would
be useful in the case of coroutines. An "inline coroutine" would
become part of its parent for the purpose of e.g. creating the
coroutine state machine.
Has anyone thought about this at all? Any alternatives?
Regards, Phil.
Inline in C++ has different meaning in compiler. But I guess you already knew this : )
I think that your idea for "inline coroutine" would be the proposal.
A bottleneck for this idea I could see is that this is hard to implement. For example,
the C++ coroutine would be splitted in clang. And clang/LLVM banned inlining a coroutine
before it gets splitted due to complicated semantic problems.
I understand that this is a language list so that "it is hard to implement" might not be
a good argument. And another problem that any idea that want to mark
special attribute for coroutine might met is that it couldn't handle indirect call and definitions
in another TU.
For example, if I mark a virtual coroutine as "inline coroutine", then the compiler is unable to
know the callee during compilation time. This is similar for functions whose definition are in
another TU. This is beyond "the compiler is hard to implement". I think it is constrained by the
fundamental design.
There would be other problems. For example, what would happen if a "inline coroutine" get called
in normal function. What would happen if a "inline coroutine" get called in a coroutine with different
coroutine promise_type? I believe it would be very complicated.
Finally, I don't think the call overhead might be significant. My experience for the performance of coroutine
is that the main overhead comes from dynamic allocation. Another one is exception. If you are
not in an environment that could disable exception, it might be helpful to mark many functions/coroutines as noexcept.
And the performanace advantage of coroutine occurs when the concurrency is very high.
It would absolutely good to optimize the performance of coroutine in single thread. But the performance of coroutine
would be worse than normal function after all since it generates more code.
Thanks,
Chuanqi
------------------------------------------------------------------
From:Phil Endecott via Std-Proposals <std-proposals_at_[hidden]>
Send Time:2021年12月10日(星期五) 00:28
To:std-proposals <std-proposals_at_[hidden]>
Cc:Phil Endecott <std_proposals_list_at_[hidden]>
Subject:[std-proposals] inline coroutine generators
Dear Experts,
I have recently been experimenting with generators for the
first time.
One issue that bothers me is inlining. For example:
generator<char> g1()
{
for (.....) {
co_yield x;
if (......) g2(a);
if (......) g2(b);
g2(a+b);
}
}
static ??? g2(int)
{
for (....) {
co_yield ....;
}
}
What I'm trying to convey with that pseudocode is that I've
decomposed a largish block of code by factoring out some common
bits into another routine. If these were functions this would be
unproblematic; the compiler would likely inline and if it didn't
the function call overhead would be modest. But because it's a
coroutine, things are more complicated. Given the complexity of
the recursive generator implementation, I don't think that there
is any real prospect of g2 being properly inlined into g1, is
there?
What bothers me is that if I wrote g2 as a macro, it would of
course be perfectly inlined.
We don't want to find that we have a choice between (a) over-long
functions with duplicated code, (b) macros, (c) nicely organised
code that is slow.
This makes me wonder if some special meaning for "inline" would
be useful in the case of coroutines. An "inline coroutine" would
become part of its parent for the purpose of e.g. creating the
coroutine state machine.
Has anyone thought about this at all? Any alternatives?
Regards, Phil.
-- Std-Proposals mailing list Std-Proposals_at_lists.isocpp.org https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2021-12-09 21:05:48